Merge "Update compatibility library tests" into jb-mr1-dev
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 8711ad7..2287859 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -135,6 +135,7 @@
 $(call add-clean-step, rm -f $(PRODUCT_OUT)/system/media/video/Disco*)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/ImageProcessing_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/ImageProcessing2_intermediates)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067.jpg b/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067.jpg
new file mode 100644
index 0000000..05d3ee2
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067b.jpg b/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067b.jpg
new file mode 100644
index 0000000..aed0781
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067b.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/ImageProcessing2/res/layout/main.xml b/tests/RenderScriptTests/ImageProcessing2/res/layout/main.xml
index bd56d62..f0a2b92 100644
--- a/tests/RenderScriptTests/ImageProcessing2/res/layout/main.xml
+++ b/tests/RenderScriptTests/ImageProcessing2/res/layout/main.xml
@@ -54,6 +54,10 @@
                 android:id="@+id/filterselection"
                 android:layout_width="fill_parent"
                 android:layout_height="wrap_content"/>
+            <Spinner
+                android:id="@+id/spinner1"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
             <TextView
                 android:id="@+id/slider1Text"
                 android:layout_width="match_parent"
@@ -124,6 +128,11 @@
                 android:layout_marginRight="10sp"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"/>
+            <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/benchmark_all"
+                    android:onClick="benchmark_all"/>
             </LinearLayout>
     </ScrollView>
 </LinearLayout>
diff --git a/tests/RenderScriptTests/ImageProcessing2/res/values/strings.xml b/tests/RenderScriptTests/ImageProcessing2/res/values/strings.xml
index cc5cc4d..a7dd165 100644
--- a/tests/RenderScriptTests/ImageProcessing2/res/values/strings.xml
+++ b/tests/RenderScriptTests/ImageProcessing2/res/values/strings.xml
@@ -29,5 +29,6 @@
     <string name="gamma">Gamma</string>
     <string name="saturation">Saturation</string>
     <string name="benchmark">Benchmark</string>
+    <string name="benchmark_all">Benchmark All</string>
 
 </resources>
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blend.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blend.java
new file mode 100644
index 0000000..ac02101
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blend.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2012 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 com.android.rs.image2;
+
+import java.lang.Math;
+import java.lang.Short;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.view.View;
+import android.widget.Spinner;
+
+public class Blend extends TestBase {
+    private ScriptIntrinsicBlend mBlend;
+    private ScriptC_blend mBlendHelper;
+    private short image1Alpha = 128;
+    private short image2Alpha = 128;
+
+    String mIntrinsicNames[];
+
+    private Allocation image1;
+    private Allocation image2;
+    private int currentIntrinsic = 0;
+
+    private AdapterView.OnItemSelectedListener mIntrinsicSpinnerListener =
+            new AdapterView.OnItemSelectedListener() {
+                public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                    currentIntrinsic = pos;
+                    runTest();
+                    act.updateDisplay();
+                }
+
+                public void onNothingSelected(AdapterView parent) {
+
+                }
+            };
+
+    public void createTest(android.content.res.Resources res) {
+        mBlend = ScriptIntrinsicBlend.create(mRS, Element.U8_4(mRS));
+        mBlendHelper = new ScriptC_blend(mRS);
+        mBlendHelper.set_alpha((short)128);
+
+        image1 = Allocation.createTyped(mRS, mInPixelsAllocation.getType());
+        image2 = Allocation.createTyped(mRS, mInPixelsAllocation2.getType());
+
+        mIntrinsicNames = new String[14];
+        mIntrinsicNames[0] = "Source";
+        mIntrinsicNames[1] = "Destination";
+        mIntrinsicNames[2] = "Source Over";
+        mIntrinsicNames[3] = "Destination Over";
+        mIntrinsicNames[4] = "Source In";
+        mIntrinsicNames[5] = "Destination In";
+        mIntrinsicNames[6] = "Source Out";
+        mIntrinsicNames[7] = "Destination Out";
+        mIntrinsicNames[8] = "Source Atop";
+        mIntrinsicNames[9] = "Destination Atop";
+        mIntrinsicNames[10] = "XOR";
+        mIntrinsicNames[11] = "Add";
+        mIntrinsicNames[12] = "Subtract";
+        mIntrinsicNames[13] = "Multiply";
+    }
+
+    public boolean onSpinner1Setup(Spinner s) {
+        s.setAdapter(new ArrayAdapter<String>(
+            act, R.layout.spinner_layout, mIntrinsicNames));
+        s.setOnItemSelectedListener(mIntrinsicSpinnerListener);
+        return true;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Image 1 Alpha");
+        b.setMax(255);
+        b.setProgress(image1Alpha);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        image1Alpha = (short)progress;
+    }
+
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Image 2 Alpha");
+        b.setMax(255);
+        b.setProgress(image2Alpha);
+        return true;
+    }
+
+    public void onBar2Changed(int progress) {
+        image2Alpha = (short)progress;
+    }
+
+    public void runTest() {
+        image1.copy2DRangeFrom(0, 0, mInPixelsAllocation.getType().getX(), mInPixelsAllocation.getType().getY(), mInPixelsAllocation, 0, 0);
+        image2.copy2DRangeFrom(0, 0, mInPixelsAllocation2.getType().getX(), mInPixelsAllocation2.getType().getY(), mInPixelsAllocation2, 0, 0);
+
+        mBlendHelper.set_alpha(image1Alpha);
+        mBlendHelper.forEach_setImageAlpha(image1);
+
+        mBlendHelper.set_alpha(image2Alpha);
+        mBlendHelper.forEach_setImageAlpha(image2);
+
+        switch (currentIntrinsic) {
+        case 0:
+            mBlend.forEachSrc(image1, image2);
+            break;
+        case 1:
+            mBlend.forEachDst(image1, image2);
+            break;
+        case 2:
+            mBlend.forEachSrcOver(image1, image2);
+            break;
+        case 3:
+            mBlend.forEachDstOver(image1, image2);
+            break;
+        case 4:
+            mBlend.forEachSrcIn(image1, image2);
+            break;
+        case 5:
+            mBlend.forEachDstIn(image1, image2);
+            break;
+        case 6:
+            mBlend.forEachSrcOut(image1, image2);
+            break;
+        case 7:
+            mBlend.forEachDstOut(image1, image2);
+            break;
+        case 8:
+            mBlend.forEachSrcAtop(image1, image2);
+            break;
+        case 9:
+            mBlend.forEachDstAtop(image1, image2);
+            break;
+        case 10:
+            mBlend.forEachXor(image1, image2);
+            break;
+        case 11:
+            mBlend.forEachAdd(image1, image2);
+            break;
+        case 12:
+            mBlend.forEachSubtract(image1, image2);
+            break;
+        case 13:
+            mBlend.forEachMultiply(image1, image2);
+            break;
+        }
+
+        mOutPixelsAllocation.copy2DRangeFrom(0, 0, image2.getType().getX(), image2.getType().getY(), image2, 0, 0);
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blur25.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blur25.java
index be87716..b518b02 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blur25.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blur25.java
@@ -24,37 +24,38 @@
 import android.widget.TextView;
 
 public class Blur25 extends TestBase {
+    private boolean mUseIntrinsic = false;
+    private ScriptIntrinsicBlur mIntrinsic;
+
     private int MAX_RADIUS = 25;
     private ScriptC_threshold mScript;
-    private ScriptC_vertical_blur mScriptVBlur;
-    private ScriptC_horizontal_blur mScriptHBlur;
-    private int mRadius = MAX_RADIUS;
+    private float mRadius = MAX_RADIUS;
     private float mSaturation = 1.0f;
     private Allocation mScratchPixelsAllocation1;
     private Allocation mScratchPixelsAllocation2;
 
 
+    public Blur25(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
     public boolean onBar1Setup(SeekBar b, TextView t) {
         t.setText("Radius");
         b.setProgress(100);
         return true;
     }
-    public boolean onBar2Setup(SeekBar b, TextView t) {
-        b.setProgress(50);
-        t.setText("Saturation");
-        return true;
-    }
 
 
     public void onBar1Changed(int progress) {
-        float fRadius = progress / 100.0f;
-        fRadius *= (float)(MAX_RADIUS);
-        mRadius = (int)fRadius;
-        mScript.set_radius(mRadius);
-    }
-    public void onBar2Changed(int progress) {
-        mSaturation = (float)progress / 50.0f;
-        mScriptVBlur.invoke_setSaturation(mSaturation);
+        mRadius = ((float)progress) / 100.0f * MAX_RADIUS;
+        if (mRadius <= 0.10f) {
+            mRadius = 0.10f;
+        }
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(mRadius);
+        } else {
+            mScript.invoke_setRadius((int)mRadius);
+        }
     }
 
 
@@ -62,40 +63,52 @@
         int width = mInPixelsAllocation.getType().getX();
         int height = mInPixelsAllocation.getType().getY();
 
-        Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
-        tb.setX(width);
-        tb.setY(height);
-        mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
-        mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicBlur.create(mRS, Element.U8_4(mRS));
+            mIntrinsic.setRadius(MAX_RADIUS);
+            mIntrinsic.setInput(mInPixelsAllocation);
+        } else {
 
-        mScriptVBlur = new ScriptC_vertical_blur(mRS, res, R.raw.vertical_blur);
-        mScriptHBlur = new ScriptC_horizontal_blur(mRS, res, R.raw.horizontal_blur);
+            Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
+            tb.setX(width);
+            tb.setY(height);
+            mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
+            mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
 
-        mScript = new ScriptC_threshold(mRS, res, R.raw.threshold);
-        mScript.set_width(width);
-        mScript.set_height(height);
-        mScript.set_radius(mRadius);
+            mScript = new ScriptC_threshold(mRS, res, R.raw.threshold);
+            mScript.set_width(width);
+            mScript.set_height(height);
+            mScript.invoke_setRadius(MAX_RADIUS);
 
-        mScriptVBlur.invoke_setSaturation(mSaturation);
-
-        mScript.bind_InPixel(mInPixelsAllocation);
-        mScript.bind_OutPixel(mOutPixelsAllocation);
-        mScript.bind_ScratchPixel1(mScratchPixelsAllocation1);
-        mScript.bind_ScratchPixel2(mScratchPixelsAllocation2);
-
-        mScript.set_vBlurScript(mScriptVBlur);
-        mScript.set_hBlurScript(mScriptHBlur);
+            mScript.set_InPixel(mInPixelsAllocation);
+            mScript.set_ScratchPixel1(mScratchPixelsAllocation1);
+            mScript.set_ScratchPixel2(mScratchPixelsAllocation2);
+        }
     }
 
     public void runTest() {
-        mScript.invoke_filter();
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mOutPixelsAllocation);
+        } else {
+            mScript.forEach_copyIn(mInPixelsAllocation, mScratchPixelsAllocation1);
+            mScript.forEach_horz(mScratchPixelsAllocation2);
+            mScript.forEach_vert(mOutPixelsAllocation);
+        }
     }
 
     public void setupBenchmark() {
-        mScript.set_radius(MAX_RADIUS);
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(MAX_RADIUS);
+        } else {
+            mScript.invoke_setRadius(MAX_RADIUS);
+        }
     }
 
     public void exitBenchmark() {
-        mScript.set_radius(mRadius);
+        if (mUseIntrinsic) {
+            mIntrinsic.setRadius(mRadius);
+        } else {
+            mScript.invoke_setRadius((int)mRadius);
+        }
     }
 }
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ColorMatrix.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ColorMatrix.java
new file mode 100644
index 0000000..3b0f86a
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ColorMatrix.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2012 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 com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class ColorMatrix extends TestBase {
+    private ScriptC_colormatrix mScript;
+    private ScriptIntrinsicColorMatrix mIntrinsic;
+    private boolean mUseIntrinsic;
+    private boolean mUseGrey;
+
+    public ColorMatrix(boolean useIntrinsic, boolean useGrey) {
+        mUseIntrinsic = useIntrinsic;
+        mUseGrey = useGrey;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        Matrix4f m = new Matrix4f();
+        m.set(1, 0, 0.2f);
+        m.set(1, 1, 0.9f);
+        m.set(1, 2, 0.2f);
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
+            if (mUseGrey) {
+                mIntrinsic.setGreyscale();
+            } else {
+                mIntrinsic.setColorMatrix(m);
+            }
+        } else {
+            mScript = new ScriptC_colormatrix(mRS, res, R.raw.colormatrix);
+            mScript.invoke_setMatrix(m);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mInPixelsAllocation, mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve3x3.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve3x3.java
new file mode 100644
index 0000000..7635e13
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve3x3.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 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 com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class Convolve3x3 extends TestBase {
+    private ScriptC_convolve3x3 mScript;
+    private ScriptIntrinsicConvolve3x3 mIntrinsic;
+
+    private int mWidth;
+    private int mHeight;
+    private boolean mUseIntrinsic;
+
+    public Convolve3x3(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mWidth = mInPixelsAllocation.getType().getX();
+        mHeight = mInPixelsAllocation.getType().getY();
+
+        float f[] = new float[9];
+        f[0] =  0.f;    f[1] = -1.f;    f[2] =  0.f;
+        f[3] = -1.f;    f[4] =  5.f;    f[5] = -1.f;
+        f[6] =  0.f;    f[7] = -1.f;    f[8] =  0.f;
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
+            mIntrinsic.setCoefficients(f);
+            mIntrinsic.setInput(mInPixelsAllocation);
+        } else {
+            mScript = new ScriptC_convolve3x3(mRS, res, R.raw.convolve3x3);
+            mScript.set_gCoeffs(f);
+            mScript.set_gIn(mInPixelsAllocation);
+            mScript.set_gWidth(mWidth);
+            mScript.set_gHeight(mHeight);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve5x5.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve5x5.java
new file mode 100644
index 0000000..d2da3c4
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve5x5.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2012 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 com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class Convolve5x5 extends TestBase {
+    private ScriptC_convolve5x5 mScript;
+    private ScriptIntrinsicConvolve5x5 mIntrinsic;
+
+    private int mWidth;
+    private int mHeight;
+    private boolean mUseIntrinsic;
+
+    public Convolve5x5(boolean useIntrinsic) {
+        mUseIntrinsic = useIntrinsic;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mWidth = mInPixelsAllocation.getType().getX();
+        mHeight = mInPixelsAllocation.getType().getY();
+
+        float f[] = new float[25];
+        //f[0] = 0.012f; f[1] = 0.025f; f[2] = 0.031f; f[3] = 0.025f; f[4] = 0.012f;
+        //f[5] = 0.025f; f[6] = 0.057f; f[7] = 0.075f; f[8] = 0.057f; f[9] = 0.025f;
+        //f[10]= 0.031f; f[11]= 0.075f; f[12]= 0.095f; f[13]= 0.075f; f[14]= 0.031f;
+        //f[15]= 0.025f; f[16]= 0.057f; f[17]= 0.075f; f[18]= 0.057f; f[19]= 0.025f;
+        //f[20]= 0.012f; f[21]= 0.025f; f[22]= 0.031f; f[23]= 0.025f; f[24]= 0.012f;
+
+        //f[0] = 1.f; f[1] = 2.f; f[2] = 0.f; f[3] = -2.f; f[4] = -1.f;
+        //f[5] = 4.f; f[6] = 8.f; f[7] = 0.f; f[8] = -8.f; f[9] = -4.f;
+        //f[10]= 6.f; f[11]=12.f; f[12]= 0.f; f[13]=-12.f; f[14]= -6.f;
+        //f[15]= 4.f; f[16]= 8.f; f[17]= 0.f; f[18]= -8.f; f[19]= -4.f;
+        //f[20]= 1.f; f[21]= 2.f; f[22]= 0.f; f[23]= -2.f; f[24]= -1.f;
+
+        f[0] = -1.f; f[1] = -3.f; f[2] = -4.f; f[3] = -3.f; f[4] = -1.f;
+        f[5] = -3.f; f[6] =  0.f; f[7] =  6.f; f[8] =  0.f; f[9] = -3.f;
+        f[10]= -4.f; f[11]=  6.f; f[12]= 20.f; f[13]=  6.f; f[14]= -4.f;
+        f[15]= -3.f; f[16]=  0.f; f[17]=  6.f; f[18]=  0.f; f[19]= -3.f;
+        f[20]= -1.f; f[21]= -3.f; f[22]= -4.f; f[23]= -3.f; f[24]= -1.f;
+
+        if (mUseIntrinsic) {
+            mIntrinsic = ScriptIntrinsicConvolve5x5.create(mRS, Element.U8_4(mRS));
+            mIntrinsic.setCoefficients(f);
+            mIntrinsic.setInput(mInPixelsAllocation);
+        } else {
+            mScript = new ScriptC_convolve5x5(mRS, res, R.raw.convolve5x5);
+            mScript.set_gCoeffs(f);
+            mScript.set_gIn(mInPixelsAllocation);
+            mScript.set_gWidth(mWidth);
+            mScript.set_gHeight(mHeight);
+        }
+    }
+
+    public void runTest() {
+        if (mUseIntrinsic) {
+            mIntrinsic.forEach(mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mOutPixelsAllocation);
+        }
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Copy.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Copy.java
new file mode 100644
index 0000000..ef71907
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Copy.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 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 com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class Copy extends TestBase {
+    private ScriptC_copy mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_copy(mRS, res, R.raw.copy);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/CrossProcess.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/CrossProcess.java
new file mode 100644
index 0000000..96787d7
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/CrossProcess.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2012 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 com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class CrossProcess extends TestBase {
+    private ScriptIntrinsicLUT mIntrinsic;
+
+    public void createTest(android.content.res.Resources res) {
+        mIntrinsic = ScriptIntrinsicLUT.create(mRS, Element.U8_4(mRS));
+        for (int ct=0; ct < 256; ct++) {
+            float f = ((float)ct) / 255.f;
+
+            float r = f;
+            if (r < 0.5f) {
+                r = 4.0f * r * r * r;
+            } else {
+                r = 1.0f - r;
+                r = 1.0f - (4.0f * r * r * r);
+            }
+            mIntrinsic.setRed(ct, (int)(r * 255.f + 0.5f));
+
+            float g = f;
+            if (g < 0.5f) {
+                g = 2.0f * g * g;
+            } else {
+                g = 1.0f - g;
+                g = 1.0f - (2.0f * g * g);
+            }
+            mIntrinsic.setGreen(ct, (int)(g * 255.f + 0.5f));
+
+            float b = f * 0.5f + 0.25f;
+            mIntrinsic.setBlue(ct, (int)(b * 255.f + 0.5f));
+        }
+
+    }
+
+    public void runTest() {
+        mIntrinsic.forEach(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Fisheye.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Fisheye.java
index 995cf9d..97beb88 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Fisheye.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Fisheye.java
@@ -23,12 +23,16 @@
 public class Fisheye extends TestBase {
     private ScriptC_fisheye_full mScript_full = null;
     private ScriptC_fisheye_relaxed mScript_relaxed = null;
+    private ScriptC_fisheye_approx_full mScript_approx_full = null;
+    private ScriptC_fisheye_approx_relaxed mScript_approx_relaxed = null;
+    private final boolean approx;
     private final boolean relaxed;
     private float center_x = 0.5f;
     private float center_y = 0.5f;
     private float scale = 0.5f;
 
-    public Fisheye(boolean relaxed) {
+    public Fisheye(boolean approx, boolean relaxed) {
+        this.approx = approx;
         this.relaxed = relaxed;
     }
 
@@ -65,7 +69,18 @@
     }
 
     private void do_init() {
-        if (relaxed)
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.invoke_init_filter(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale);
+            else
+                mScript_approx_full.invoke_init_filter(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale);
+        } else if (relaxed)
             mScript_relaxed.invoke_init_filter(
                     mInPixelsAllocation.getType().getX(),
                     mInPixelsAllocation.getType().getY(), center_x, center_y,
@@ -78,7 +93,19 @@
     }
 
     public void createTest(android.content.res.Resources res) {
-        if (relaxed) {
+        if (approx) {
+            if (relaxed) {
+                mScript_approx_relaxed = new ScriptC_fisheye_approx_relaxed(mRS,
+                        res, R.raw.fisheye_approx_relaxed);
+                mScript_approx_relaxed.set_in_alloc(mInPixelsAllocation);
+                mScript_approx_relaxed.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+            } else {
+                mScript_approx_full = new ScriptC_fisheye_approx_full(mRS, res,
+                        R.raw.fisheye_approx_full);
+                mScript_approx_full.set_in_alloc(mInPixelsAllocation);
+                mScript_approx_full.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+            }
+        } else if (relaxed) {
             mScript_relaxed = new ScriptC_fisheye_relaxed(mRS, res,
                     R.raw.fisheye_relaxed);
             mScript_relaxed.set_in_alloc(mInPixelsAllocation);
@@ -93,7 +120,12 @@
     }
 
     public void runTest() {
-        if (relaxed)
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.forEach_root(mOutPixelsAllocation);
+            else
+                mScript_approx_full.forEach_root(mOutPixelsAllocation);
+        } else if (relaxed)
             mScript_relaxed.forEach_root(mOutPixelsAllocation);
         else
             mScript_full.forEach_root(mOutPixelsAllocation);
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Grain.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Grain.java
index e00edd7..dfd3c32 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Grain.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Grain.java
@@ -40,19 +40,40 @@
         mScript.set_gNoiseStrength(s);
     }
 
+    private int findHighBit(int v) {
+        int bit = 0;
+        while (v > 1) {
+            bit++;
+            v >>= 1;
+        }
+        return bit;
+    }
+
+
     public void createTest(android.content.res.Resources res) {
         int width = mInPixelsAllocation.getType().getX();
         int height = mInPixelsAllocation.getType().getY();
 
+        int noiseW = findHighBit(width);
+        int noiseH = findHighBit(height);
+        if (noiseW > 9) {
+            noiseW = 9;
+        }
+        if (noiseH > 9) {
+            noiseH = 9;
+        }
+        noiseW = 1 << noiseW;
+        noiseH = 1 << noiseH;
+
         Type.Builder tb = new Type.Builder(mRS, Element.U8(mRS));
-        tb.setX(width);
-        tb.setY(height);
+        tb.setX(noiseW);
+        tb.setY(noiseH);
         mNoise = Allocation.createTyped(mRS, tb.create());
         mNoise2 = Allocation.createTyped(mRS, tb.create());
 
         mScript = new ScriptC_grain(mRS, res, R.raw.grain);
-        mScript.set_gWidth(width);
-        mScript.set_gHeight(height);
+        mScript.set_gWMask(noiseW - 1);
+        mScript.set_gHMask(noiseH - 1);
         mScript.set_gNoiseStrength(0.5f);
         mScript.set_gBlendSource(mNoise);
         mScript.set_gNoise(mNoise2);
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/GroupTest.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/GroupTest.java
index b9fbb59..a7ceebee 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/GroupTest.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/GroupTest.java
@@ -22,8 +22,8 @@
 import android.util.Log;
 
 public class GroupTest extends TestBase {
-    private ScriptC_convolve3x3 mConvolve;
-    private ScriptC_colormatrix mMatrix;
+    private ScriptIntrinsicConvolve3x3 mConvolve;
+    private ScriptIntrinsicColorMatrix mMatrix;
 
     private Allocation mScratchPixelsAllocation1;
     private ScriptGroup mGroup;
@@ -41,20 +41,20 @@
         mWidth = mInPixelsAllocation.getType().getX();
         mHeight = mInPixelsAllocation.getType().getY();
 
-        mConvolve = new ScriptC_convolve3x3(mRS, res, R.raw.convolve3x3);
-        mMatrix = new ScriptC_colormatrix(mRS, res, R.raw.colormatrix);
+        mConvolve = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
+        mMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
 
         float f[] = new float[9];
         f[0] =  0.f;    f[1] = -1.f;    f[2] =  0.f;
         f[3] = -1.f;    f[4] =  5.f;    f[5] = -1.f;
         f[6] =  0.f;    f[7] = -1.f;    f[8] =  0.f;
-        mConvolve.set_gCoeffs(f);
+        mConvolve.setCoefficients(f);
 
         Matrix4f m = new Matrix4f();
         m.set(1, 0, 0.2f);
         m.set(1, 1, 0.9f);
         m.set(1, 2, 0.2f);
-        mMatrix.invoke_setMatrix(m);
+        mMatrix.setColorMatrix(m);
 
         Type.Builder tb = new Type.Builder(mRS, Element.U8_4(mRS));
         tb.setX(mWidth);
@@ -63,24 +63,23 @@
 
         if (mUseNative) {
             ScriptGroup.Builder b = new ScriptGroup.Builder(mRS);
-            b.addConnection(connect, mConvolve, mMatrix, null);
+            b.addKernel(mConvolve.getKernelID());
+            b.addKernel(mMatrix.getKernelID());
+            b.addConnection(connect, mConvolve.getKernelID(), mMatrix.getKernelID());
             mGroup = b.create();
-
         } else {
             mScratchPixelsAllocation1 = Allocation.createTyped(mRS, connect);
         }
     }
 
     public void runTest() {
-        mConvolve.set_gIn(mInPixelsAllocation);
-        mConvolve.set_gWidth(mWidth);
-        mConvolve.set_gHeight(mHeight);
+        mConvolve.setInput(mInPixelsAllocation);
         if (mUseNative) {
-            mGroup.setOutput(mMatrix, mOutPixelsAllocation);
+            mGroup.setOutput(mMatrix.getKernelID(), mOutPixelsAllocation);
             mGroup.execute();
         } else {
-            mConvolve.forEach_root(mScratchPixelsAllocation1);
-            mMatrix.forEach_root(mScratchPixelsAllocation1, mOutPixelsAllocation);
+            mConvolve.forEach(mScratchPixelsAllocation1);
+            mMatrix.forEach(mScratchPixelsAllocation1, mOutPixelsAllocation);
         }
     }
 
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java
index 9b36da14..227518f 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java
@@ -34,13 +34,27 @@
 import android.util.Log;
 import java.lang.Math;
 
+import android.os.Environment;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
 public class ImageProcessingActivity2 extends Activity
                                        implements SeekBar.OnSeekBarChangeListener {
     private final String TAG = "Img";
+    private final String RESULT_FILE = "image_processing_result.csv";
+
     Bitmap mBitmapIn;
+    Bitmap mBitmapIn2;
     Bitmap mBitmapOut;
     String mTestNames[];
 
+    private Spinner mSpinner;
     private SeekBar mBar1;
     private SeekBar mBar2;
     private SeekBar mBar3;
@@ -64,6 +78,10 @@
 
     private TestBase mTest;
 
+    public void updateDisplay() {
+            mTest.updateBitmap(mBitmapOut);
+            mDisplayView.invalidate();
+    }
 
     public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
         if (fromUser) {
@@ -81,8 +99,7 @@
             }
 
             mTest.runTest();
-            mTest.updateBitmap(mBitmapOut);
-            mDisplayView.invalidate();
+            updateDisplay();
         }
     }
 
@@ -93,6 +110,9 @@
     }
 
     void setupBars() {
+        mSpinner.setVisibility(View.VISIBLE);
+        mTest.onSpinner1Setup(mSpinner);
+
         mBar1.setVisibility(View.VISIBLE);
         mText1.setVisibility(View.VISIBLE);
         mTest.onBar1Setup(mBar1, mText1);
@@ -116,6 +136,9 @@
 
 
     void changeTest(int testID) {
+        if (mTest != null) {
+            mTest.destroy();
+        }
         switch(testID) {
         case 0:
             mTest = new LevelsV4(false, false);
@@ -130,58 +153,122 @@
             mTest = new LevelsV4(true, true);
             break;
         case 4:
-            mTest = new Blur25();
+            mTest = new Blur25(false);
             break;
         case 5:
-            mTest = new Greyscale();
+            mTest = new Blur25(true);
             break;
         case 6:
-            mTest = new Grain();
+            mTest = new Greyscale();
             break;
         case 7:
-            mTest = new Fisheye(false);
+            mTest = new Grain();
             break;
         case 8:
-            mTest = new Fisheye(true);
+            mTest = new Fisheye(false, false);
             break;
         case 9:
-            mTest = new Vignette(false);
+            mTest = new Fisheye(false, true);
             break;
         case 10:
-            mTest = new Vignette(true);
+            mTest = new Fisheye(true, false);
             break;
         case 11:
-            mTest = new GroupTest(false);
+            mTest = new Fisheye(true, true);
             break;
         case 12:
+            mTest = new Vignette(false, false);
+            break;
+        case 13:
+            mTest = new Vignette(false, true);
+            break;
+        case 14:
+            mTest = new Vignette(true, false);
+            break;
+        case 15:
+            mTest = new Vignette(true, true);
+            break;
+        case 16:
+            mTest = new GroupTest(false);
+            break;
+        case 17:
             mTest = new GroupTest(true);
             break;
+        case 18:
+            mTest = new Convolve3x3(false);
+            break;
+        case 19:
+            mTest = new Convolve3x3(true);
+            break;
+        case 20:
+            mTest = new ColorMatrix(false, false);
+            break;
+        case 21:
+            mTest = new ColorMatrix(true, false);
+            break;
+        case 22:
+            mTest = new ColorMatrix(true, true);
+            break;
+        case 23:
+            mTest = new Copy();
+            break;
+        case 24:
+            mTest = new CrossProcess();
+            break;
+        case 25:
+            mTest = new Convolve5x5(false);
+            break;
+        case 26:
+            mTest = new Convolve5x5(true);
+            break;
+        case 27:
+            mTest = new Mandelbrot();
+            break;
+        case 28:
+            mTest = new Blend();
+            break;
         }
 
-        mTest.createBaseTest(this, mBitmapIn);
+        mTest.createBaseTest(this, mBitmapIn, mBitmapIn2);
         setupBars();
 
         mTest.runTest();
-        mTest.updateBitmap(mBitmapOut);
-        mDisplayView.invalidate();
+        updateDisplay();
         mBenchmarkResult.setText("Result: not run");
     }
 
     void setupTests() {
-        mTestNames = new String[13];
+        mTestNames = new String[29];
         mTestNames[0] = "Levels Vec3 Relaxed";
         mTestNames[1] = "Levels Vec4 Relaxed";
         mTestNames[2] = "Levels Vec3 Full";
         mTestNames[3] = "Levels Vec4 Full";
         mTestNames[4] = "Blur radius 25";
-        mTestNames[5] = "Greyscale";
-        mTestNames[6] = "Grain";
-        mTestNames[7] = "Fisheye Full";
-        mTestNames[8] = "Fisheye Relaxed";
-        mTestNames[9] = "Vignette Full";
-        mTestNames[10] = "Vignette Relaxed";
-        mTestNames[11] = "Group Test (emulated)";
-        mTestNames[12] = "Group Test (native)";
+        mTestNames[5] = "Intrinsic Blur radius 25";
+        mTestNames[6] = "Greyscale";
+        mTestNames[7] = "Grain";
+        mTestNames[8] = "Fisheye Full";
+        mTestNames[9] = "Fisheye Relaxed";
+        mTestNames[10] = "Fisheye Approximate Full";
+        mTestNames[11] = "Fisheye Approximate Relaxed";
+        mTestNames[12] = "Vignette Full";
+        mTestNames[13] = "Vignette Relaxed";
+        mTestNames[14] = "Vignette Approximate Full";
+        mTestNames[15] = "Vignette Approximate Relaxed";
+        mTestNames[16] = "Group Test (emulated)";
+        mTestNames[17] = "Group Test (native)";
+        mTestNames[18] = "Convolve 3x3";
+        mTestNames[19] = "Intrinsics Convolve 3x3";
+        mTestNames[20] = "ColorMatrix";
+        mTestNames[21] = "Intrinsics ColorMatrix";
+        mTestNames[22] = "Intrinsics ColorMatrix Grey";
+        mTestNames[23] = "Copy";
+        mTestNames[24] = "CrossProcess (using LUT)";
+        mTestNames[25] = "Convolve 5x5";
+        mTestNames[26] = "Intrinsics Convolve 5x5";
+        mTestNames[27] = "Mandelbrot";
+        mTestNames[28] = "Intrinsics Blend";
+
         mTestSpinner.setAdapter(new ArrayAdapter<String>(
             this, R.layout.spinner_layout, mTestNames));
     }
@@ -202,14 +289,17 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
 
-        mBitmapIn = loadBitmap(R.drawable.city);
-        mBitmapOut = loadBitmap(R.drawable.city);
+        mBitmapIn = loadBitmap(R.drawable.img1600x1067);
+        mBitmapIn2 = loadBitmap(R.drawable.img1600x1067b);
+        mBitmapOut = loadBitmap(R.drawable.img1600x1067);
 
         mSurfaceView = (SurfaceView) findViewById(R.id.surface);
 
         mDisplayView = (ImageView) findViewById(R.id.display);
         mDisplayView.setImageBitmap(mBitmapOut);
 
+        mSpinner = (Spinner) findViewById(R.id.spinner1);
+
         mBar1 = (SeekBar) findViewById(R.id.slider1);
         mBar2 = (SeekBar) findViewById(R.id.slider2);
         mBar3 = (SeekBar) findViewById(R.id.slider3);
@@ -255,37 +345,69 @@
 
     // button hook
     public void benchmark(View v) {
-        long t = getBenchmark();
+        float t = getBenchmark();
         //long javaTime = javaFilter();
         //mBenchmarkResult.setText("RS: " + t + " ms  Java: " + javaTime + " ms");
         mBenchmarkResult.setText("Result: " + t + " ms");
+        Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t);
+    }
+
+    public void benchmark_all(View v) {
+        // write result into a file
+        File externalStorage = Environment.getExternalStorageDirectory();
+        if (!externalStorage.canWrite()) {
+            Log.v(TAG, "sdcard is not writable");
+            return;
+        }
+        File resultFile = new File(externalStorage, RESULT_FILE);
+        //resultFile.setWritable(true, false);
+        try {
+            BufferedWriter rsWriter = new BufferedWriter(new FileWriter(resultFile));
+            Log.v(TAG, "Saved results in: " + resultFile.getAbsolutePath());
+            for (int i = 0; i < mTestNames.length; i++ ) {
+                changeTest(i);
+                float t = getBenchmark();
+                String s = new String("" + mTestNames[i] + ", " + t);
+                rsWriter.write(s + "\n");
+                Log.v(TAG, "Test " + s + "ms\n");
+            }
+            rsWriter.close();
+        } catch (IOException e) {
+            Log.v(TAG, "Unable to write result file " + e.getMessage());
+        }
+        changeTest(0);
     }
 
     // For benchmark test
-    public long getBenchmark() {
+    public float getBenchmark() {
         mDoingBenchmark = true;
 
         mTest.setupBenchmark();
         long result = 0;
 
-        Log.v(TAG, "Warming");
-        long t = java.lang.System.currentTimeMillis() + 2000;
+        //Log.v(TAG, "Warming");
+        long t = java.lang.System.currentTimeMillis() + 250;
         do {
             mTest.runTest();
             mTest.finish();
         } while (t > java.lang.System.currentTimeMillis());
 
 
-        Log.v(TAG, "Benchmarking");
+        //Log.v(TAG, "Benchmarking");
+        int ct = 0;
         t = java.lang.System.currentTimeMillis();
-        mTest.runTest();
-        mTest.finish();
+        do {
+            mTest.runTest();
+            mTest.finish();
+            ct++;
+        } while ((t+1000) > java.lang.System.currentTimeMillis());
         t = java.lang.System.currentTimeMillis() - t;
+        float ft = (float)t;
+        ft /= ct;
 
-        Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t);
         mTest.exitBenchmark();
         mDoingBenchmark = false;
 
-        return t;
+        return ft;
     }
 }
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.java
new file mode 100644
index 0000000..556d797
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2012 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 com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Mandelbrot extends TestBase {
+    private ScriptC_mandelbrot mScript;
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Iterations");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        int iters = progress * 3 + 50;
+        mScript.set_gMaxIteration(iters);
+    }
+
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Lower Bound: X");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar2Changed(int progress) {
+        float scaleFactor = mScript.get_scaleFactor();
+        // allow viewport to be moved by 2x scale factor
+        float lowerBoundX = -2.f + ((progress / scaleFactor) / 50.f);
+        mScript.set_lowerBoundX(lowerBoundX);
+    }
+
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        t.setText("Lower Bound: Y");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar3Changed(int progress) {
+        float scaleFactor = mScript.get_scaleFactor();
+        // allow viewport to be moved by 2x scale factor
+        float lowerBoundY = -2.f + ((progress / scaleFactor) / 50.f);
+        mScript.set_lowerBoundY(lowerBoundY);
+    }
+
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        t.setText("Scale Factor");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar4Changed(int progress) {
+        float scaleFactor = 4.f - (3.96f * (progress / 100.f));
+        mScript.set_scaleFactor(scaleFactor);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mOutPixelsAllocation.getType().getX();
+        int height = mOutPixelsAllocation.getType().getY();
+
+        mScript = new ScriptC_mandelbrot(mRS, res, R.raw.mandelbrot);
+        mScript.set_gDimX(width);
+        mScript.set_gDimY(height);
+        mScript.set_gMaxIteration(50);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mOutPixelsAllocation);
+        mRS.finish();
+    }
+
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.java
index 35170af..9df2eff 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.java
@@ -31,14 +31,18 @@
 import android.view.View;
 import android.util.Log;
 import java.lang.Math;
+import android.widget.Spinner;
 
 public class TestBase  {
     protected final String TAG = "Img";
 
     protected RenderScript mRS;
     protected Allocation mInPixelsAllocation;
+    protected Allocation mInPixelsAllocation2;
     protected Allocation mOutPixelsAllocation;
 
+    protected ImageProcessingActivity2 act;
+
     // Override to use UI elements
     public void onBar1Changed(int progress) {
     }
@@ -79,11 +83,20 @@
         return false;
     }
 
-    public final void createBaseTest(ImageProcessingActivity2 act, Bitmap b) {
+    public boolean onSpinner1Setup(Spinner s) {
+        s.setVisibility(View.INVISIBLE);
+        return false;
+    }
+
+    public final void createBaseTest(ImageProcessingActivity2 ipact, Bitmap b, Bitmap b2) {
+        act = ipact;
         mRS = RenderScript.create(act);
         mInPixelsAllocation = Allocation.createFromBitmap(mRS, b,
                                                           Allocation.MipmapControl.MIPMAP_NONE,
                                                           Allocation.USAGE_SCRIPT);
+        mInPixelsAllocation2 = Allocation.createFromBitmap(mRS, b2,
+                                                          Allocation.MipmapControl.MIPMAP_NONE,
+                                                          Allocation.USAGE_SCRIPT);
         mOutPixelsAllocation = Allocation.createFromBitmap(mRS, b,
                                                            Allocation.MipmapControl.MIPMAP_NONE,
                                                            Allocation.USAGE_SCRIPT);
@@ -103,6 +116,10 @@
         mRS.finish();
     }
 
+    public void destroy() {
+        mRS.destroy();
+    }
+
     public void updateBitmap(Bitmap b) {
         mOutPixelsAllocation.copyTo(b);
     }
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Vignette.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Vignette.java
index fc69eba..8618d5a 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Vignette.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Vignette.java
@@ -23,6 +23,9 @@
 public class Vignette extends TestBase {
     private ScriptC_vignette_full mScript_full = null;
     private ScriptC_vignette_relaxed mScript_relaxed = null;
+    private ScriptC_vignette_approx_full mScript_approx_full = null;
+    private ScriptC_vignette_approx_relaxed mScript_approx_relaxed = null;
+    private final boolean approx;
     private final boolean relaxed;
     private float center_x = 0.5f;
     private float center_y = 0.5f;
@@ -30,7 +33,8 @@
     private float shade = 0.5f;
     private float slope = 20.0f;
 
-    public Vignette(boolean relaxed) {
+    public Vignette(boolean approx, boolean relaxed) {
+        this.approx = approx;
         this.relaxed = relaxed;
     }
 
@@ -87,7 +91,18 @@
     }
 
     private void do_init() {
-        if (relaxed)
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.invoke_init_vignette(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale, shade, slope);
+            else
+                mScript_approx_full.invoke_init_vignette(
+                        mInPixelsAllocation.getType().getX(),
+                        mInPixelsAllocation.getType().getY(), center_x,
+                        center_y, scale, shade, slope);
+        } else if (relaxed)
             mScript_relaxed.invoke_init_vignette(
                     mInPixelsAllocation.getType().getX(),
                     mInPixelsAllocation.getType().getY(), center_x, center_y,
@@ -100,21 +115,36 @@
     }
 
     public void createTest(android.content.res.Resources res) {
-        if (relaxed) {
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed = new ScriptC_vignette_approx_relaxed(
+                        mRS, res, R.raw.vignette_approx_relaxed);
+            else
+                mScript_approx_full = new ScriptC_vignette_approx_full(
+                        mRS, res, R.raw.vignette_approx_full);
+        } else if (relaxed)
             mScript_relaxed = new ScriptC_vignette_relaxed(mRS, res,
                     R.raw.vignette_relaxed);
-        } else {
+        else
             mScript_full = new ScriptC_vignette_full(mRS, res,
                     R.raw.vignette_full);
-        }
         do_init();
     }
 
     public void runTest() {
-        if (relaxed)
-            mScript_relaxed.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+        if (approx) {
+            if (relaxed)
+                mScript_approx_relaxed.forEach_root(mInPixelsAllocation,
+                        mOutPixelsAllocation);
+            else
+                mScript_approx_full.forEach_root(mInPixelsAllocation,
+                        mOutPixelsAllocation);
+        } else if (relaxed)
+            mScript_relaxed.forEach_root(mInPixelsAllocation,
+                    mOutPixelsAllocation);
         else
-            mScript_full.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+            mScript_full.forEach_root(mInPixelsAllocation,
+                    mOutPixelsAllocation);
     }
 
 }
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/blend.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/blend.rs
new file mode 100644
index 0000000..4d90725
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/blend.rs
@@ -0,0 +1,24 @@
+// Copyright (C) 2011 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.
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+
+uchar alpha = 0x0;
+
+void setImageAlpha(uchar4 *v_out, uint32_t x, uint32_t y) {
+  v_out->rgba = convert_uchar4((convert_uint4(v_out->rgba) * alpha) >> (uint4)8);
+  v_out->a = alpha;
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs
new file mode 100644
index 0000000..b110b88
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
+
+int32_t gWidth;
+int32_t gHeight;
+rs_allocation gIn;
+
+float gCoeffs[25];
+
+void root(uchar4 *out, uint32_t x, uint32_t y) {
+    uint32_t x0 = max((int32_t)x-2, 0);
+    uint32_t x1 = max((int32_t)x-1, 0);
+    uint32_t x2 = x;
+    uint32_t x3 = min((int32_t)x+1, gWidth-1);
+    uint32_t x4 = min((int32_t)x+2, gWidth-1);
+
+    uint32_t y0 = max((int32_t)y-2, 0);
+    uint32_t y1 = max((int32_t)y-1, 0);
+    uint32_t y2 = y;
+    uint32_t y3 = min((int32_t)y+1, gHeight-1);
+    uint32_t y4 = min((int32_t)y+2, gHeight-1);
+
+    float4 p0 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y0)) * gCoeffs[0]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y0)) * gCoeffs[1]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y0)) * gCoeffs[2]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y0)) * gCoeffs[3]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y0)) * gCoeffs[4];
+
+    float4 p1 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y1)) * gCoeffs[5]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y1)) * gCoeffs[6]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y1)) * gCoeffs[7]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y1)) * gCoeffs[8]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y1)) * gCoeffs[9];
+
+    float4 p2 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y2)) * gCoeffs[10]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y2)) * gCoeffs[11]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y2)) * gCoeffs[12]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y2)) * gCoeffs[13]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y2)) * gCoeffs[14];
+
+    float4 p3 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y3)) * gCoeffs[15]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y3)) * gCoeffs[16]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y3)) * gCoeffs[17]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y3)) * gCoeffs[18]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y3)) * gCoeffs[19];
+
+    float4 p4 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y4)) * gCoeffs[20]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y4)) * gCoeffs[21]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y4)) * gCoeffs[22]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y4)) * gCoeffs[23]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y4)) * gCoeffs[24];
+
+    p0 = clamp(p0 + p1 + p2 + p3 + p4, 0.f, 255.f);
+    *out = convert_uchar4(p0);
+}
+
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/copy.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/copy.rs
new file mode 100644
index 0000000..31e4241
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/copy.rs
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+
+void root(const uchar4 *v_in, uchar4 *v_out) {
+    *v_out = *v_in;
+}
+
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh
index 4dcfc1d..3809912 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh
@@ -17,46 +17,41 @@
 rs_allocation in_alloc;
 rs_sampler sampler;
 
-static float2 center, dimensions;
-static float2 scale;
-static float alpha;
-static float radius2;
-static float factor;
+static float2 center, neg_center, inv_dimensions, axis_scale;
+static float alpha, radius2, factor;
 
-void init_filter(uint32_t dim_x, uint32_t dim_y, float focus_x, float focus_y, float k) {
-    center.x = focus_x;
-    center.y = focus_y;
-    dimensions.x = (float)dim_x;
-    dimensions.y = (float)dim_y;
-
+void init_filter(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y, float k) {
+    center.x = center_x;
+    center.y = center_y;
+    neg_center = -center;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
     alpha = k * 2.0 + 0.75;
-    float bound2 = 0.25;
-    if (dim_x > dim_y) {
-        scale.x = 1.0;
-        scale.y = dimensions.y / dimensions.x;
-        bound2 *= (scale.y*scale.y + 1);
-    } else {
-        scale.x = dimensions.x / dimensions.y;
-        scale.y = 1.0;
-        bound2 *= (scale.x*scale.x + 1);
-    }
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+    
+    const float bound2 = 0.25 * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
     const float bound = sqrt(bound2);
     const float radius = 1.15 * bound;
     radius2 = radius*radius;
-    const float max_radian = 0.5f * M_PI - atan(alpha / bound * sqrt(radius2 - bound2));
+    const float max_radian = M_PI_2 - atan(alpha / bound * sqrt(radius2 - bound2));
     factor = bound / max_radian;
 }
 
 void root(uchar4 *out, uint32_t x, uint32_t y) {
     // Convert x and y to floating point coordinates with center as origin
-    float2 coord;
-    coord.x = (float)x / dimensions.x;
-    coord.y = (float)y / dimensions.y;
-    coord -= center;
-    const float dist = length(scale * coord);
-    const float radian = M_PI_2 - atan((alpha * sqrt(radius2 - dist * dist)) / dist);
-    const float scalar = radian * factor / dist;
-    const float2 new_coord = coord * scalar + center;
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float2 scaledCoord = axis_scale * coord;
+    const float dist2 = scaledCoord.x*scaledCoord.x + scaledCoord.y*scaledCoord.y;
+    const float inv_dist = rsqrt(dist2);
+    const float radian = M_PI_2 - atan((alpha * sqrt(radius2 - dist2)) * inv_dist);
+    const float scalar = radian * factor * inv_dist;
+    const float2 new_coord = mad(coord, scalar, center);
     const float4 fout = rsSample(in_alloc, sampler, new_coord);
     *out = rsPackColorTo8888(fout);
 }
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx.rsh b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx.rsh
new file mode 100644
index 0000000..08b4126
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx.rsh
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+rs_allocation in_alloc;
+rs_sampler sampler;
+
+static float2 center, neg_center, inv_dimensions, axis_scale;
+static float alpha, radius2, factor;
+
+void init_filter(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y, float k) {
+    center.x = center_x;
+    center.y = center_y;
+    neg_center = -center;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+    alpha = k * 2.0 + 0.75;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+
+    const float bound2 = 0.25 * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
+    const float bound = sqrt(bound2);
+    const float radius = 1.15 * bound;
+    radius2 = radius*radius;
+    const float max_radian = M_PI_2 - atan(alpha / bound * sqrt(radius2 - bound2));
+    factor = bound / max_radian;
+}
+
+void root(uchar4 *out, uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float2 scaledCoord = axis_scale * coord;
+    const float dist2 = scaledCoord.x*scaledCoord.x + scaledCoord.y*scaledCoord.y;
+    const float inv_dist = half_rsqrt(dist2);
+    const float radian = M_PI_2 - atan((alpha * half_sqrt(radius2 - dist2)) * inv_dist);
+    const float scalar = radian * factor * inv_dist;
+    const float2 new_coord = mad(coord, scalar, center);
+    const float4 fout = rsSample(in_alloc, sampler, new_coord);
+    *out = rsPackColorTo8888(fout);
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_full.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_full.rs
new file mode 100644
index 0000000..cce42f9
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_full.rs
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+
+#include "fisheye_approx.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs
new file mode 100644
index 0000000..64d27ed
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
+
+#include "fisheye_approx.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.rs
index 75f4021..44320a5 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.rs
@@ -38,25 +38,25 @@
  *  1  2  1
  */
 
-int32_t gWidth;
-int32_t gHeight;
+int32_t gWMask;
+int32_t gHMask;
 
 rs_allocation gBlendSource;
 void blend9(uchar *out, uint32_t x, uint32_t y) {
-    uint32_t x1 = min(x+1, (uint32_t)gWidth);
-    uint32_t x2 = max(x-1, (uint32_t)0);
-    uint32_t y1 = min(y+1, (uint32_t)gHeight);
-    uint32_t y2 = max(y-1, (uint32_t)0);
+    uint32_t x1 = (x-1) & gWMask;
+    uint32_t x2 = (x+1) & gWMask;
+    uint32_t y1 = (y-1) & gHMask;
+    uint32_t y2 = (y+1) & gHMask;
 
-    uint p00 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x1, y1))[0];
-    uint p01 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x, y1))[0];
-    uint p02 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x2, y1))[0];
-    uint p10 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x1, y))[0];
-    uint p11 = 230 * ((uchar *)rsGetElementAt(gBlendSource, x, y))[0];
-    uint p12 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x2, y))[0];
-    uint p20 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x1, y2))[0];
-    uint p21 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x, y2))[0];
-    uint p22 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x2, y2))[0];
+    uint p00 = 56 *  rsGetElementAt_uchar(gBlendSource, x1, y1);
+    uint p01 = 114 * rsGetElementAt_uchar(gBlendSource, x, y1);
+    uint p02 = 56 *  rsGetElementAt_uchar(gBlendSource, x2, y1);
+    uint p10 = 114 * rsGetElementAt_uchar(gBlendSource, x1, y);
+    uint p11 = 230 * rsGetElementAt_uchar(gBlendSource, x, y);
+    uint p12 = 114 * rsGetElementAt_uchar(gBlendSource, x2, y);
+    uint p20 = 56 *  rsGetElementAt_uchar(gBlendSource, x1, y2);
+    uint p21 = 114 * rsGetElementAt_uchar(gBlendSource, x, y2);
+    uint p22 = 56 *  rsGetElementAt_uchar(gBlendSource, x2, y2);
 
     p00 += p01;
     p02 += p10;
@@ -69,7 +69,8 @@
     p20 += p22;
     p20 += p02;
 
-    *out = (uchar)(p20 >> 10);
+    p20 = min(p20 >> 10, (uint)255);
+    *out = (uchar)p20;
 }
 
 float gNoiseStrength;
@@ -77,7 +78,7 @@
 rs_allocation gNoise;
 void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
     float4 ip = convert_float4(*in);
-    float pnoise = (float) ((uchar *)rsGetElementAt(gNoise, x, y))[0];
+    float pnoise = (float) rsGetElementAt_uchar(gNoise, x & gWMask, y & gHMask);
 
     float energy_level = ip.r + ip.g + ip.b;
     float energy_mask = (28.f - sqrt(energy_level)) * 0.03571f;
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/horizontal_blur.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/horizontal_blur.rs
deleted file mode 100644
index ee83496..0000000
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/horizontal_blur.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-#pragma version(1)
-#pragma rs_fp_relaxed
-
-#include "ip.rsh"
-
-void root(float4 *out, const void *usrData, uint32_t x, uint32_t y) {
-    const FilterStruct *fs = (const FilterStruct *)usrData;
-    float3 blurredPixel = 0;
-    const float *gPtr = fs->gaussian;
-    if ((x > fs->radius) && (x < (fs->width - fs->radius))) {
-        for (int r = -fs->radius; r <= fs->radius; r ++) {
-            const float4 *i = (const float4 *)rsGetElementAt(fs->ain, x + r, y);
-            blurredPixel += i->xyz * gPtr[0];
-            gPtr++;
-        }
-    } else {
-        for (int r = -fs->radius; r <= fs->radius; r ++) {
-            // Stepping left and right away from the pixel
-            int validX = rsClamp((int)x + r, (int)0, (int)(fs->width - 1));
-            const float4 *i = (const float4 *)rsGetElementAt(fs->ain, validX, y);
-            blurredPixel += i->xyz * gPtr[0];
-            gPtr++;
-        }
-    }
-
-    out->xyz = blurredPixel;
-}
-
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ip.rsh b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ip.rsh
deleted file mode 100644
index 0cdf9e1..0000000
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ip.rsh
+++ /dev/null
@@ -1,15 +0,0 @@
-#pragma rs java_package_name(com.android.rs.image2)
-
-#define MAX_RADIUS 25
-
-typedef struct FilterStruct_s {
-    rs_allocation ain;
-
-    float *gaussian; //[MAX_RADIUS * 2 + 1];
-    int height;
-    int width;
-    int radius;
-
-} FilterStruct;
-
-
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs
new file mode 100644
index 0000000..55e5304
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs
@@ -0,0 +1,56 @@
+// Copyright (C) 2011 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.
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+
+uint32_t gMaxIteration = 500;
+uint32_t gDimX = 1024;
+uint32_t gDimY = 1024;
+
+float lowerBoundX = -2.f;
+float lowerBoundY = -2.f;
+float scaleFactor = 4.f;
+
+void root(uchar4 *v_out, uint32_t x, uint32_t y) {
+  float2 p;
+  p.x = lowerBoundX + ((float)x / gDimX) * scaleFactor;
+  p.y = lowerBoundY + ((float)y / gDimY) * scaleFactor;
+
+  float2 t = 0;
+  float2 t2 = t * t;
+  int iter = 0;
+  while((t2.x + t2.y < 4.f) && (iter < gMaxIteration)) {
+    float xtemp = t2.x - t2.y + p.x;
+    t.y = 2 * t.x * t.y + p.y;
+    t.x = xtemp;
+    iter++;
+    t2 = t * t;
+  }
+
+  if(iter >= gMaxIteration) {
+    // write a non-transparent black pixel
+    *v_out = (uchar4){0, 0, 0, 0xff};
+  } else {
+    float mi3 = gMaxIteration / 3.;
+    if (iter <= (gMaxIteration / 3))
+      *v_out = (uchar4){0xff * (iter / mi3), 0, 0, 0xff};
+    else if (iter <= (((gMaxIteration / 3) * 2)))
+      *v_out = (uchar4){0xff - (0xff * ((iter - mi3) / mi3)),
+                        (0xff * ((iter - mi3) / mi3)), 0, 0xff};
+    else
+      *v_out = (uchar4){0, 0xff - (0xff * ((iter - (mi3 * 2)) / mi3)),
+                        (0xff * ((iter - (mi3 * 2)) / mi3)), 0xff};
+  }
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/threshold.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/threshold.rs
index 77cd5be..9ef4898 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/threshold.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/threshold.rs
@@ -1,26 +1,23 @@
 #pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
 
-#include "ip.rsh"
 
 int height;
 int width;
-int radius;
+static int radius;
 
-uchar4 * InPixel;
-uchar4 * OutPixel;
-float4 * ScratchPixel1;
-float4 * ScratchPixel2;
+rs_allocation InPixel;
+rs_allocation ScratchPixel1;
+rs_allocation ScratchPixel2;
 
-rs_script vBlurScript;
-rs_script hBlurScript;
-
-const int CMD_FINISHED = 1;
+const int MAX_RADIUS = 25;
 
 // Store our coefficients here
 static float gaussian[MAX_RADIUS * 2 + 1];
 
-
-static void computeGaussianWeights() {
+void setRadius(int rad) {
+    radius = rad;
     // Compute gaussian weights for the blur
     // e is the euler's number
     float e = 2.718281828459045f;
@@ -45,8 +42,7 @@
 
     float normalizeFactor = 0.0f;
     float floatR = 0.0f;
-    int r;
-    for (r = -radius; r <= radius; r ++) {
+    for (int r = -radius; r <= radius; r ++) {
         floatR = (float)r;
         gaussian[r + radius] = coeff1 * pow(e, floatR * floatR * coeff2);
         normalizeFactor += gaussian[r + radius];
@@ -54,40 +50,57 @@
 
     //Now we need to normalize the weights because all our coefficients need to add up to one
     normalizeFactor = 1.0f / normalizeFactor;
-    for (r = -radius; r <= radius; r ++) {
+    for (int r = -radius; r <= radius; r ++) {
         floatR = (float)r;
         gaussian[r + radius] *= normalizeFactor;
     }
 }
 
-
-static void copyInput() {
-    rs_allocation ain;
-    ain = rsGetAllocation(InPixel);
-    uint32_t dimx = rsAllocationGetDimX(ain);
-    uint32_t dimy = rsAllocationGetDimY(ain);
-    for (uint32_t y = 0; y < dimy; y++) {
-        for (uint32_t x = 0; x < dimx; x++) {
-            ScratchPixel1[x + y * dimx] = convert_float4(InPixel[x + y * dimx]);
-        }
-    }
+void copyIn(const uchar4 *in, float4 *out) {
+    *out = convert_float4(*in);
 }
 
-void filter() {
-    copyInput();
-    computeGaussianWeights();
+void vert(uchar4 *out, uint32_t x, uint32_t y) {
+    float3 blurredPixel = 0;
+    const float *gPtr = gaussian;
+    if ((y > radius) && (y < (height - radius))) {
+        for (int r = -radius; r <= radius; r ++) {
+            const float4 *i = (const float4 *)rsGetElementAt(ScratchPixel2, x, y + r);
+            blurredPixel += i->xyz * gPtr[0];
+            gPtr++;
+        }
+    } else {
+        for (int r = -radius; r <= radius; r ++) {
+            int validH = rsClamp((int)y + r, (int)0, (int)(height - 1));
+            const float4 *i = (const float4 *)rsGetElementAt(ScratchPixel2, x, validH);
+            blurredPixel += i->xyz * gPtr[0];
+            gPtr++;
+        }
+    }
 
-    FilterStruct fs;
-    fs.gaussian = gaussian;
-    fs.width = width;
-    fs.height = height;
-    fs.radius = radius;
+    out->xyz = convert_uchar3(clamp(blurredPixel, 0.f, 255.f));
+    out->w = 0xff;
+}
 
-    fs.ain = rsGetAllocation(ScratchPixel1);
-    rsForEach(hBlurScript, fs.ain, rsGetAllocation(ScratchPixel2), &fs, sizeof(fs));
+void horz(float4 *out, uint32_t x, uint32_t y) {
+    float3 blurredPixel = 0;
+    const float *gPtr = gaussian;
+    if ((x > radius) && (x < (width - radius))) {
+        for (int r = -radius; r <= radius; r ++) {
+            const float4 *i = (const float4 *)rsGetElementAt(ScratchPixel1, x + r, y);
+            blurredPixel += i->xyz * gPtr[0];
+            gPtr++;
+        }
+    } else {
+        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));
+            const float4 *i = (const float4 *)rsGetElementAt(ScratchPixel1, validX, y);
+            blurredPixel += i->xyz * gPtr[0];
+            gPtr++;
+        }
+    }
 
-    fs.ain = rsGetAllocation(ScratchPixel2);
-    rsForEach(vBlurScript, fs.ain, rsGetAllocation(OutPixel), &fs, sizeof(fs));
-    //rsSendToClientBlocking(CMD_FINISHED);
+    out->xyz = blurredPixel;
 }
 
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vertical_blur.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vertical_blur.rs
deleted file mode 100644
index 60fd71b..0000000
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vertical_blur.rs
+++ /dev/null
@@ -1,59 +0,0 @@
-#pragma version(1)
-#pragma rs_fp_relaxed
-
-#include "ip.rsh"
-
-static float saturation;
-static rs_matrix3x3 colorMat;
-
-void setSaturation(float sat) {
-    saturation = sat;
-
-    // Saturation
-    // Linear weights
-    //float rWeight = 0.3086f;
-    //float gWeight = 0.6094f;
-    //float bWeight = 0.0820f;
-
-    // Gamma 2.2 weights (we haven't converted our image to linear space yet for perf reasons)
-    float rWeight = 0.299f;
-    float gWeight = 0.587f;
-    float bWeight = 0.114f;
-
-    float oneMinusS = 1.0f - saturation;
-    rsMatrixSet(&colorMat, 0, 0, oneMinusS * rWeight + saturation);
-    rsMatrixSet(&colorMat, 0, 1, oneMinusS * rWeight);
-    rsMatrixSet(&colorMat, 0, 2, oneMinusS * rWeight);
-    rsMatrixSet(&colorMat, 1, 0, oneMinusS * gWeight);
-    rsMatrixSet(&colorMat, 1, 1, oneMinusS * gWeight + saturation);
-    rsMatrixSet(&colorMat, 1, 2, oneMinusS * gWeight);
-    rsMatrixSet(&colorMat, 2, 0, oneMinusS * bWeight);
-    rsMatrixSet(&colorMat, 2, 1, oneMinusS * bWeight);
-    rsMatrixSet(&colorMat, 2, 2, oneMinusS * bWeight + saturation);
-}
-
-void root(uchar4 *out, const void *usrData, uint32_t x, uint32_t y) {
-    const FilterStruct *fs = (const FilterStruct *)usrData;
-    float3 blurredPixel = 0;
-    const float *gPtr = fs->gaussian;
-    if ((y > fs->radius) && (y < (fs->height - fs->radius))) {
-        for (int r = -fs->radius; r <= fs->radius; r ++) {
-            const float4 *i = (const float4 *)rsGetElementAt(fs->ain, x, y + r);
-            blurredPixel += i->xyz * gPtr[0];
-            gPtr++;
-        }
-    } else {
-        for (int r = -fs->radius; r <= fs->radius; r ++) {
-            int validH = rsClamp((int)y + r, (int)0, (int)(fs->height - 1));
-            const float4 *i = (const float4 *)rsGetElementAt(fs->ain, x, validH);
-            blurredPixel += i->xyz * gPtr[0];
-            gPtr++;
-        }
-    }
-
-    float3 temp = rsMatrixMultiply(&colorMat, blurredPixel);
-    temp = clamp(temp, 0.f, 255.f);
-    out->xyz = convert_uchar3(temp);
-    out->w = 0xff;
-}
-
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx.rsh b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx.rsh
new file mode 100644
index 0000000..7f7bdcf
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx.rsh
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+static float2 neg_center, axis_scale, inv_dimensions;
+static float sloped_neg_range, sloped_inv_max_dist, shade, opp_shade;
+
+void init_vignette(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y,
+        float desired_scale, float desired_shade, float desired_slope) {
+
+    neg_center.x = -center_x;
+    neg_center.y = -center_y;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+
+    const float max_dist = 0.5 * length(axis_scale);
+    sloped_inv_max_dist = desired_slope * 1.f/max_dist;
+
+    // Range needs to be between 1.3 to 0.6. When scale is zero then range is
+    // 1.3 which means no vignette at all because the luminousity difference is
+    // less than 1/256.  Expect input scale to be between 0.0 and 1.0.
+    const float neg_range = 0.7*sqrt(desired_scale) - 1.3;
+    sloped_neg_range = exp(neg_range * desired_slope);
+
+    shade = desired_shade;
+    opp_shade = 1.f - desired_shade;
+}
+
+void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float4 fin = convert_float4(*in);
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float sloped_dist_ratio = fast_length(axis_scale * coord)  * sloped_inv_max_dist;
+    // TODO:  add half_exp once implemented
+    const float lumen = opp_shade + shade * half_recip(1.f + sloped_neg_range * exp(sloped_dist_ratio));
+    float4 fout;
+    fout.rgb = fin.rgb * lumen;
+    fout.w = fin.w;
+    *out = convert_uchar4(fout);
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_full.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_full.rs
new file mode 100644
index 0000000..3612509
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_full.rs
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+
+#include "vignette_approx.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs
new file mode 100644
index 0000000..b714e9b
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
+
+#include "vignette_approx.rsh"
+