Merge "Define calculatedValue for all paths."
diff --git a/driver/runtime/Android.mk b/driver/runtime/Android.mk
index b4c0445..f505d9f 100755
--- a/driver/runtime/Android.mk
+++ b/driver/runtime/Android.mk
@@ -123,8 +123,7 @@
 RS_TRIPLE_CFLAGS :=
 LOCAL_MODULE := librsrt_arm.bc
 LOCAL_IS_HOST_MODULE := true
-LOCAL_SRC_FILES := $(clcore_files)
-LOCAL_SRC_FILES_32 := $(clcore_files_32)
+LOCAL_SRC_FILES := $(clcore_files) $(clcore_files_32)
 include $(LOCAL_PATH)/build_bc_lib.mk
 
 # Build the MIPS version of the library
@@ -137,8 +136,7 @@
 RS_TRIPLE_CFLAGS :=
 LOCAL_MODULE := librsrt_mips.bc
 LOCAL_IS_HOST_MODULE := true
-LOCAL_SRC_FILES := $(clcore_files)
-LOCAL_SRC_FILES_32 := $(clcore_files_32)
+LOCAL_SRC_FILES := $(clcore_files) $(clcore_files_32)
 include $(LOCAL_PATH)/build_bc_lib.mk
 
 # Build the x86 version of the library
@@ -151,8 +149,7 @@
 RS_TRIPLE_CFLAGS := -D__i386__
 LOCAL_MODULE := librsrt_x86.bc
 LOCAL_IS_HOST_MODULE := true
-LOCAL_SRC_FILES := $(clcore_x86_files)
-LOCAL_SRC_FILES_32 := $(clcore_files_32)
+LOCAL_SRC_FILES := $(clcore_x86_files) $(clcore_base_files_32)
 include $(LOCAL_PATH)/build_bc_lib.mk
 
 
@@ -164,6 +161,5 @@
 RS_TRIPLE_CFLAGS :=
 LOCAL_MODULE := librsrt_arm64.bc
 LOCAL_IS_HOST_MODULE := true
-LOCAL_SRC_FILES := $(clcore_files)
-LOCAL_SRC_FILES_64 := $(clcore_files_64)
+LOCAL_SRC_FILES := $(clcore_files) $(clcore_files_64)
 include $(LOCAL_PATH)/build_bc_lib.mk
diff --git a/java/tests/HelloComputeNDK/Android.mk b/java/tests/HelloComputeNDK/Android.mk
index 5f1bd17..d4194b5 100644
--- a/java/tests/HelloComputeNDK/Android.mk
+++ b/java/tests/HelloComputeNDK/Android.mk
@@ -26,6 +26,7 @@
 
 LOCAL_PACKAGE_NAME := HelloComputeNDK
 LOCAL_SDK_VERSION := 14
+LOCAL_32_BIT_ONLY := true
 
 LOCAL_JNI_SHARED_LIBRARIES := libhellocomputendk
 
diff --git a/java/tests/ImageProcessing2/Android.mk b/java/tests/ImageProcessing2/Android.mk
index a6d5ec9..9c53d91 100644
--- a/java/tests/ImageProcessing2/Android.mk
+++ b/java/tests/ImageProcessing2/Android.mk
@@ -25,7 +25,7 @@
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-v8-renderscript
 
 LOCAL_PACKAGE_NAME := ImageProcessing2
-LOCAL_SDK_VERSION := 8
+LOCAL_SDK_VERSION := 14
 LOCAL_RENDERSCRIPT_TARGET_API := 18
 LOCAL_RENDERSCRIPT_COMPATIBILITY := 18
 LOCAL_RENDERSCRIPT_INCLUDES_OVERRIDE := $(TOPDIR)external/clang/lib/Headers \
diff --git a/java/tests/ImageProcessing2/AndroidManifest.xml b/java/tests/ImageProcessing2/AndroidManifest.xml
index 0129fa8..0f89c35 100644
--- a/java/tests/ImageProcessing2/AndroidManifest.xml
+++ b/java/tests/ImageProcessing2/AndroidManifest.xml
@@ -3,11 +3,19 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.rs.image2">
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-    <uses-sdk android:minSdkVersion="8" />
-    <application android:label="IP GB">
+    <uses-sdk android:minSdkVersion="14" />
+    <application android:label="IP-Compat"
+                 android:hardwareAccelerated="true"
+                 android:theme="@android:style/Theme.Holo.Light">
         <activity android:name="ImageProcessingActivity2">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
+
+        <activity class=".IPControls" android:name="IPControls">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
diff --git a/java/tests/ImageProcessing2/res/drawable-hdpi/ic_action_settings.png b/java/tests/ImageProcessing2/res/drawable-hdpi/ic_action_settings.png
new file mode 100644
index 0000000..54eecde
--- /dev/null
+++ b/java/tests/ImageProcessing2/res/drawable-hdpi/ic_action_settings.png
Binary files differ
diff --git a/java/tests/ImageProcessing2/res/drawable-mdpi/ic_action_settings.png b/java/tests/ImageProcessing2/res/drawable-mdpi/ic_action_settings.png
new file mode 100644
index 0000000..25c36db
--- /dev/null
+++ b/java/tests/ImageProcessing2/res/drawable-mdpi/ic_action_settings.png
Binary files differ
diff --git a/java/tests/ImageProcessing2/res/drawable-nodpi/city.png b/java/tests/ImageProcessing2/res/drawable-nodpi/city.png
deleted file mode 100644
index 856eeff..0000000
--- a/java/tests/ImageProcessing2/res/drawable-nodpi/city.png
+++ /dev/null
Binary files differ
diff --git a/java/tests/ImageProcessing2/res/drawable-nodpi/img1280x720a.jpg b/java/tests/ImageProcessing2/res/drawable-nodpi/img1280x720a.jpg
new file mode 100644
index 0000000..ff09574
--- /dev/null
+++ b/java/tests/ImageProcessing2/res/drawable-nodpi/img1280x720a.jpg
Binary files differ
diff --git a/java/tests/ImageProcessing2/res/drawable-nodpi/img1280x720b.jpg b/java/tests/ImageProcessing2/res/drawable-nodpi/img1280x720b.jpg
new file mode 100644
index 0000000..e9f6aa4
--- /dev/null
+++ b/java/tests/ImageProcessing2/res/drawable-nodpi/img1280x720b.jpg
Binary files differ
diff --git a/java/tests/ImageProcessing2/res/drawable-nodpi/img1600x1067.jpg b/java/tests/ImageProcessing2/res/drawable-nodpi/img1600x1067.jpg
deleted file mode 100644
index 05d3ee2..0000000
--- a/java/tests/ImageProcessing2/res/drawable-nodpi/img1600x1067.jpg
+++ /dev/null
Binary files differ
diff --git a/java/tests/ImageProcessing2/res/drawable-nodpi/img1600x1067b.jpg b/java/tests/ImageProcessing2/res/drawable-nodpi/img1600x1067b.jpg
deleted file mode 100644
index aed0781..0000000
--- a/java/tests/ImageProcessing2/res/drawable-nodpi/img1600x1067b.jpg
+++ /dev/null
Binary files differ
diff --git a/java/tests/ImageProcessing2/res/drawable-nodpi/img1920x1080a.jpg b/java/tests/ImageProcessing2/res/drawable-nodpi/img1920x1080a.jpg
new file mode 100644
index 0000000..80b16ab
--- /dev/null
+++ b/java/tests/ImageProcessing2/res/drawable-nodpi/img1920x1080a.jpg
Binary files differ
diff --git a/java/tests/ImageProcessing2/res/drawable-nodpi/img1920x1080b.jpg b/java/tests/ImageProcessing2/res/drawable-nodpi/img1920x1080b.jpg
new file mode 100644
index 0000000..b4883d6
--- /dev/null
+++ b/java/tests/ImageProcessing2/res/drawable-nodpi/img1920x1080b.jpg
Binary files differ
diff --git a/java/tests/ImageProcessing2/res/drawable-nodpi/img800x450a.jpg b/java/tests/ImageProcessing2/res/drawable-nodpi/img800x450a.jpg
new file mode 100644
index 0000000..6d5b623
--- /dev/null
+++ b/java/tests/ImageProcessing2/res/drawable-nodpi/img800x450a.jpg
Binary files differ
diff --git a/java/tests/ImageProcessing2/res/drawable-nodpi/img800x450b.jpg b/java/tests/ImageProcessing2/res/drawable-nodpi/img800x450b.jpg
new file mode 100644
index 0000000..2013e07
--- /dev/null
+++ b/java/tests/ImageProcessing2/res/drawable-nodpi/img800x450b.jpg
Binary files differ
diff --git a/java/tests/ImageProcessing2/res/drawable-xhdpi/ic_action_settings.png b/java/tests/ImageProcessing2/res/drawable-xhdpi/ic_action_settings.png
new file mode 100644
index 0000000..425a8bc
--- /dev/null
+++ b/java/tests/ImageProcessing2/res/drawable-xhdpi/ic_action_settings.png
Binary files differ
diff --git a/java/tests/ImageProcessing2/res/drawable-xxhdpi/ic_action_settings.png b/java/tests/ImageProcessing2/res/drawable-xxhdpi/ic_action_settings.png
new file mode 100644
index 0000000..fe5fec4
--- /dev/null
+++ b/java/tests/ImageProcessing2/res/drawable-xxhdpi/ic_action_settings.png
Binary files differ
diff --git a/java/tests/ImageProcessing2/res/layout/controls.xml b/java/tests/ImageProcessing2/res/layout/controls.xml
new file mode 100644
index 0000000..6b5021e
--- /dev/null
+++ b/java/tests/ImageProcessing2/res/layout/controls.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:orientation="vertical"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:id="@+id/toplevel">
+
+    <ListView
+        android:id="@+id/test_list"
+        android:layout_weight="0.2"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"/>
+
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="fill_parent" android:layout_height="wrap_content">
+        <Button
+             android:id="@+id/run"
+             android:layout_width="wrap_content"
+             android:layout_height="wrap_content"
+             android:text="@string/benchmark"
+             android:onClick="btnRun"/>
+        <Button
+             android:id="@+id/select_all"
+             android:layout_width="wrap_content"
+             android:layout_height="wrap_content"
+             android:text="@string/select_all"
+             android:onClick="btnSelAll"/>
+        <Button
+             android:id="@+id/select_none"
+             android:layout_width="wrap_content"
+             android:layout_height="wrap_content"
+             android:text="@string/select_none"
+             android:onClick="btnSelNone"/>
+    </LinearLayout>
+
+    <TextView
+        android:id="@+id/results"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textSize="8pt"
+        android:layout_marginLeft="10sp"
+        android:layout_marginTop="15sp"
+        android:text="@string/results"/>
+
+</LinearLayout>
+
diff --git a/java/tests/ImageProcessing2/res/layout/main.xml b/java/tests/ImageProcessing2/res/layout/main.xml
index f0a2b92..765c7b1 100644
--- a/java/tests/ImageProcessing2/res/layout/main.xml
+++ b/java/tests/ImageProcessing2/res/layout/main.xml
@@ -36,27 +36,13 @@
                 android:layout_height="wrap_content" />
             <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                 android:orientation="horizontal"
-                android:layout_width="fill_parent"
+                android:layout_width="wrap_content"
                 android:layout_height="wrap_content">
-                    <Button
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:text="@string/benchmark"
-                        android:onClick="benchmark"/>
-                    <TextView
-                        android:id="@+id/benchmarkText"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:textSize="8pt"
-                        android:text="@string/saturation"/>
             </LinearLayout>
-            <Spinner
-                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_width="wrap_content"
                 android:layout_height="wrap_content"/>
             <TextView
                 android:id="@+id/slider1Text"
@@ -128,11 +114,6 @@
                 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/java/tests/ImageProcessing2/res/layout/spinner_layout.xml b/java/tests/ImageProcessing2/res/layout/spinner_layout.xml
index 8196bbf..7e9590e 100644
--- a/java/tests/ImageProcessing2/res/layout/spinner_layout.xml
+++ b/java/tests/ImageProcessing2/res/layout/spinner_layout.xml
@@ -18,6 +18,6 @@
 <TextView xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
-    android:padding="10dp"
-    android:textSize="16sp"
+    android:padding="2sp"
+    android:textSize="14sp"
 />
diff --git a/java/tests/ImageProcessing2/res/menu/main_activity_actions.xml b/java/tests/ImageProcessing2/res/menu/main_activity_actions.xml
new file mode 100644
index 0000000..df0159b
--- /dev/null
+++ b/java/tests/ImageProcessing2/res/menu/main_activity_actions.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+    <item android:id="@+id/action_res"
+          android:title="@string/action_res"
+          android:icon="@drawable/ic_action_settings"
+          android:showAsAction="always"
+          android:actionViewClass="android.widget.Spinner" />
+
+
+    <item android:id="@+id/action_settings"
+          android:icon="@drawable/ic_action_settings"
+          android:title="@string/action_settings"
+          android:showAsAction="always"/>
+
+</menu>
diff --git a/java/tests/ImageProcessing2/res/values/strings.xml b/java/tests/ImageProcessing2/res/values/strings.xml
index a7dd165..c8f9bc4 100644
--- a/java/tests/ImageProcessing2/res/values/strings.xml
+++ b/java/tests/ImageProcessing2/res/values/strings.xml
@@ -29,6 +29,26 @@
     <string name="gamma">Gamma</string>
     <string name="saturation">Saturation</string>
     <string name="benchmark">Benchmark</string>
-    <string name="benchmark_all">Benchmark All</string>
+
+    <string name="results">Results: not run</string>
+    <string name="length_long">Long run</string>
+    <string name="length_short">Long run</string>
+    <string name="select_all">All</string>
+    <string name="select_none">None</string>
+
+    <string name="action_settings">Setting</string>
+    <string name="action_resolution">Resolution</string>
+
+    <string name="action_res">res</string>
+    <string name="ok">Ok</string>
+    <string name="cancel">Cancel</string>
+    <string name="settings">settings</string>
+    <string-array
+        name="settings_array">
+        <item>Animate paramaters during benchmark</item>
+        <item>Display output while testing</item>
+        <item>Run each test longer, 10 seconds</item>
+        <item>Pause 10 seconds between tests</item>
+    </string-array>
 
 </resources>
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Artistic1.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Artistic1.java
new file mode 100644
index 0000000..611b1c4
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Artistic1.java
@@ -0,0 +1,41 @@
+/*
+ * 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 android.support.v8.renderscript.*;
+
+public class Artistic1 extends TestBase {
+    private ScriptC_artistic1 mScript;
+    private Allocation mBlured;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_artistic1(mRS);
+        mBlured = Allocation.createTyped(mRS, mInPixelsAllocation.getType());
+        mScript.set_gBlur(mBlured);
+
+        ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create(mRS, Element.U8_4(mRS));
+        blur.setRadius(20);
+        blur.setInput(mInPixelsAllocation);
+        blur.forEach(mBlured);
+    }
+
+    public void runTest() {
+        mScript.invoke_setup();
+        mScript.forEach_process(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Blend.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Blend.java
index d81ba88..7513bd4 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/Blend.java
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Blend.java
@@ -46,7 +46,7 @@
                     currentIntrinsic = pos;
                     if (mRS != null) {
                         runTest();
-                        act.updateDisplay();
+                        act.mProcessor.update();
                     }
                 }
 
@@ -114,10 +114,10 @@
         image2.copy2DRangeFrom(0, 0, mInPixelsAllocation2.getType().getX(), mInPixelsAllocation2.getType().getY(), mInPixelsAllocation2, 0, 0);
 
         mBlendHelper.set_alpha(image1Alpha);
-        mBlendHelper.forEach_setImageAlpha(image1);
+        mBlendHelper.forEach_setImageAlpha(image1, image1);
 
         mBlendHelper.set_alpha(image2Alpha);
-        mBlendHelper.forEach_setImageAlpha(image2);
+        mBlendHelper.forEach_setImageAlpha(image2, image2);
 
         switch (currentIntrinsic) {
         case 0:
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Blur25.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Blur25.java
index fb5db18..374693b 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/Blur25.java
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Blur25.java
@@ -95,20 +95,4 @@
             mScript.forEach_vert(mOutPixelsAllocation);
         }
     }
-
-    public void setupBenchmark() {
-        if (mUseIntrinsic) {
-            mIntrinsic.setRadius(MAX_RADIUS);
-        } else {
-            mScript.invoke_setRadius(MAX_RADIUS);
-        }
-    }
-
-    public void exitBenchmark() {
-        if (mUseIntrinsic) {
-            mIntrinsic.setRadius(mRadius);
-        } else {
-            mScript.invoke_setRadius((int)mRadius);
-        }
-    }
 }
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Blur25G.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Blur25G.java
index 19aa9f7..0d6939e 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/Blur25G.java
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Blur25G.java
@@ -76,14 +76,6 @@
         mIntrinsic.forEach(mScratchPixelsAllocation2);
     }
 
-    public void setupBenchmark() {
-        mIntrinsic.setRadius(MAX_RADIUS);
-    }
-
-    public void exitBenchmark() {
-        mIntrinsic.setRadius(mRadius);
-    }
-
     public void updateBitmap(Bitmap b) {
         mScript.forEach_toU8_4(mScratchPixelsAllocation2, mOutPixelsAllocation);
         mOutPixelsAllocation.copyTo(b);
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/ColorMatrix.java b/java/tests/ImageProcessing2/src/com/android/rs/image/ColorMatrix.java
index 9a43f03..8da1615 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/ColorMatrix.java
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/ColorMatrix.java
@@ -51,6 +51,22 @@
         }
     }
 
+    public void animateBars(float time) {
+        Matrix4f m = new Matrix4f();
+        m.set(1, 0, (time + 0.2f) % 1.0f);
+        m.set(1, 1, (time + 0.9f) % 1.0f);
+        m.set(1, 2, (time + 0.4f) % 1.0f);
+        if (mUseIntrinsic) {
+            if (mUseGrey) {
+                return;
+            } else {
+                mIntrinsic.setColorMatrix(m);
+            }
+        } else {
+            mScript.invoke_setMatrix(m);
+        }
+    }
+
     public void runTest() {
         if (mUseIntrinsic) {
             mIntrinsic.forEach(mInPixelsAllocation, mOutPixelsAllocation);
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Convolve3x3.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Convolve3x3.java
index 32c5846..89342dc 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/Convolve3x3.java
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Convolve3x3.java
@@ -22,7 +22,7 @@
 import android.util.Log;
 
 public class Convolve3x3 extends TestBase {
-    private ScriptC_ip2_convolve3x3 mScript;
+    private ScriptC_convolve3x3 mScript;
     private ScriptIntrinsicConvolve3x3 mIntrinsic;
 
     private int mWidth;
@@ -33,21 +33,32 @@
         mUseIntrinsic = useIntrinsic;
     }
 
+    private float blend(float v1, float v2, float p) {
+        return (v2 * p) + (v1 * (1.f-p));
+    }
+
+    private float[] updateMatrix(float str) {
+        float f[] = new float[9];
+        float cf1 = blend(1.f / 9.f, 0.f, str);
+        float cf2 = blend(1.f / 9.f, -1.f, str);
+        float cf3 = blend(1.f / 9.f, 5.f, str);
+        f[0] =  cf1;  f[1] = cf2;   f[2] = cf1;
+        f[3] =  cf2;  f[4] = cf3;   f[5] = cf2;
+        f[6] =  cf1;  f[7] = cf2;   f[8] = cf1;
+        return f;
+    }
+
     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;
-
+        float f[] = updateMatrix(1.f);
         if (mUseIntrinsic) {
             mIntrinsic = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
             mIntrinsic.setCoefficients(f);
             mIntrinsic.setInput(mInPixelsAllocation);
         } else {
-            mScript = new ScriptC_ip2_convolve3x3(mRS);
+            mScript = new ScriptC_convolve3x3(mRS);
             mScript.set_gCoeffs(f);
             mScript.set_gIn(mInPixelsAllocation);
             mScript.set_gWidth(mWidth);
@@ -55,6 +66,15 @@
         }
     }
 
+    public void animateBars(float time) {
+        float f[] = updateMatrix(time % 1.f);
+        if (mUseIntrinsic) {
+            mIntrinsic.setCoefficients(f);
+        } else {
+            mScript.set_gCoeffs(f);
+        }
+    }
+
     public void runTest() {
         if (mUseIntrinsic) {
             mIntrinsic.forEach(mOutPixelsAllocation);
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Convolve5x5.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Convolve5x5.java
index 411e2a8..0dc4103 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/Convolve5x5.java
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Convolve5x5.java
@@ -33,11 +33,33 @@
         mUseIntrinsic = useIntrinsic;
     }
 
+    private float blend(float v1, float v2, float p) {
+        return (v2 * p) + (v1 * (1.f-p));
+    }
+
+    private float[] updateMatrix(float str) {
+        float f[] = new float[25];
+        final float f125 = 1.f / 25.f;
+        float cf1 = blend(f125, -1.f, str);
+        float cf2 = blend(f125, -3.f, str);
+        float cf3 = blend(f125, -4.f, str);
+        float cf4 = blend(f125, 6.f, str);
+        float cf5 = blend(f125, 20.f, str);
+        float cf6 = blend(f125, 0.f, str);
+        f[0] = cf1;  f[1] = cf2; f[2] = cf3; f[3] = cf2; f[4] = cf1;
+        f[5] = cf2;  f[6] = cf6; f[7] = cf4; f[8] = cf6; f[9] = cf2;
+        f[10]= cf3;  f[11]= cf4; f[12]= cf5; f[13]= cf4; f[14]= cf3;
+        f[15]= cf2;  f[16]= cf6; f[17]= cf4; f[18]= cf6; f[19]= cf2;
+        f[20]= cf1;  f[21]= cf2; f[22]= cf3; f[23]= cf2; f[24]= cf1;
+        return f;
+    }
+
+
     public void createTest(android.content.res.Resources res) {
         mWidth = mInPixelsAllocation.getType().getX();
         mHeight = mInPixelsAllocation.getType().getY();
 
-        float f[] = new float[25];
+        float f[] = updateMatrix(1.f);
         //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;
@@ -50,12 +72,6 @@
         //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);
@@ -69,6 +85,15 @@
         }
     }
 
+    public void animateBars(float time) {
+        float f[] = updateMatrix(time % 1.f);
+        if (mUseIntrinsic) {
+            mIntrinsic.setCoefficients(f);
+        } else {
+            mScript.set_gCoeffs(f);
+        }
+    }
+
     public void runTest() {
         if (mUseIntrinsic) {
             mIntrinsic.forEach(mOutPixelsAllocation);
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Fisheye.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Fisheye.java
index 80a2fb4..22bdd8e 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/Fisheye.java
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Fisheye.java
@@ -68,6 +68,11 @@
         do_init();
     }
 
+    public void animateBars(float time) {
+        scale = time % 2.f;
+        do_init();
+    }
+
     private void do_init() {
         if (approx) {
             if (relaxed)
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Grain.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Grain.java
index 4dac265..4939ea3 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/Grain.java
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Grain.java
@@ -40,6 +40,11 @@
         mScript.set_gNoiseStrength(s);
     }
 
+    public void animateBars(float time) {
+        mScript.set_gNoiseStrength(time % 1.f);
+    }
+
+
     private int findHighBit(int v) {
         int bit = 0;
         while (v > 1) {
@@ -84,6 +89,5 @@
         mScript.forEach_blend9(mNoise2);
         mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
     }
-
 }
 
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/GroupTest.java b/java/tests/ImageProcessing2/src/com/android/rs/image/GroupTest.java
index a7ceebe..c224574 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/GroupTest.java
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/GroupTest.java
@@ -72,6 +72,14 @@
         }
     }
 
+    public void animateBars(float time) {
+        Matrix4f m = new Matrix4f();
+        m.set(1, 0, (time + 0.2f) % 1.0f);
+        m.set(1, 1, (time + 0.9f) % 1.0f);
+        m.set(1, 2, (time + 0.4f) % 1.0f);
+        mMatrix.setColorMatrix(m);
+    }
+
     public void runTest() {
         mConvolve.setInput(mInPixelsAllocation);
         if (mUseNative) {
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/IPControls.java b/java/tests/ImageProcessing2/src/com/android/rs/image/IPControls.java
new file mode 100644
index 0000000..b99c187
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/IPControls.java
@@ -0,0 +1,351 @@
+/*
+ * 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 com.android.rs.image2;
+
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MenuInflater;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.graphics.Point;
+import android.view.SurfaceView;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.Spinner;
+import android.widget.ToggleButton;
+import android.widget.TextView;
+import android.widget.CompoundButton;
+import android.widget.ListView;
+import android.view.View;
+import java.util.ArrayList;
+import java.util.ListIterator;
+import android.util.Log;
+import android.content.Intent;
+
+import android.os.Environment;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+public class IPControls extends Activity {
+    private final String TAG = "Img";
+    public final String RESULT_FILE = "ip_compat_result.csv";
+
+    private Spinner mResSpinner;
+    private ListView mTestListView;
+    private TextView mResultView;
+
+    private ArrayAdapter<String> mTestListAdapter;
+    private ArrayList<String> mTestList = new ArrayList<String>();
+
+    private boolean mSettings[] = {true, true, true, false, false, false};
+    // Not supported in compatibility library version
+    //private static final int SETTING_USE_IO = 0;
+    private static final int SETTING_ANIMATE = 1;
+    private static final int SETTING_DISPLAY = 2;
+    private static final int SETTING_LONG_RUN = 3;
+    private static final int SETTING_PAUSE = 4;
+
+    private float mResults[];
+
+    public enum Resolutions {
+        RES_1080P(1920, 1080, "1080p (1920x1080)"),
+        RES_720P(1280, 720, "720p (1280x720)"),
+        RES_WVGA(800, 480, "WVGA (800x480)");
+
+        private final String name;
+        public final int width;
+        public final int height;
+
+        private Resolutions(int w, int h, String s) {
+            width = w;
+            height = h;
+            name = s;
+        }
+
+        // return quoted string as displayed test name
+        public String toString() {
+            return name;
+        }
+    }
+    private Resolutions mRes;
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        // Inflate the menu items for use in the action bar
+        MenuInflater inflater = getMenuInflater();
+        inflater.inflate(R.menu.main_activity_actions, menu);
+
+        MenuItem searchItem = menu.findItem(R.id.action_res);
+        mResSpinner = (Spinner) searchItem.getActionView();
+
+        mResSpinner.setOnItemSelectedListener(mResSpinnerListener);
+        mResSpinner.setAdapter(new ArrayAdapter<Resolutions>(
+            this, R.layout.spinner_layout, Resolutions.values()));
+
+        // Choose one of the image sizes that close to the resolution
+        // of the screen.
+        Point size = new Point();
+        getWindowManager().getDefaultDisplay().getSize(size);
+        int md = (size.x > size.y) ? size.x : size.y;
+        for (int ct=0; ct < Resolutions.values().length; ct++) {
+            if (Resolutions.values()[ct].width <= (int)(md * 1.2)) {
+                mResSpinner.setSelection(ct);
+                break;
+            }
+        }
+
+        return super.onCreateOptionsMenu(menu);
+    }
+
+
+    private AdapterView.OnItemSelectedListener mResSpinnerListener =
+            new AdapterView.OnItemSelectedListener() {
+                public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                    mRes = Resolutions.values()[pos];
+                }
+
+                public void onNothingSelected(AdapterView parent) {
+                }
+            };
+
+    void launchDemo(int id) {
+        IPTestList.TestName t[] = IPTestList.TestName.values();
+
+        int testList[] = new int[1];
+        testList[0] = id;
+
+        Intent intent = makeBasicLaunchIntent();
+        intent.putExtra("tests", testList);
+        intent.putExtra("demo", true);
+        startActivityForResult(intent, 0);
+    }
+
+    void init() {
+
+        for (int i=0; i < IPTestList.TestName.values().length; i++) {
+            mTestList.add(IPTestList.TestName.values()[i].toString());
+        }
+
+        mTestListView = (ListView) findViewById(R.id.test_list);
+        mTestListAdapter = new ArrayAdapter(this,
+                android.R.layout.simple_list_item_activated_1,
+                mTestList);
+
+        mTestListView.setAdapter(mTestListAdapter);
+        mTestListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
+        mTestListAdapter.notifyDataSetChanged();
+
+        mResultView = (TextView) findViewById(R.id.results);
+
+        mTestListView.setOnItemLongClickListener(new ListView.OnItemLongClickListener() {
+                public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
+                        int pos, long id) {
+                    launchDemo(pos);
+                    return true;
+                }
+            });
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.controls);
+        init();
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+
+        //cleanup();
+    }
+
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+       // init();
+    }
+
+    private void checkGroup(int group) {
+        IPTestList.TestName t[] = IPTestList.TestName.values();
+        for (int i=0; i < t.length; i++) {
+            mTestListView.setItemChecked(i, group == t[i].group);
+        }
+    }
+
+    Intent makeBasicLaunchIntent() {
+        Intent intent = new Intent(this, ImageProcessingActivity2.class);
+        intent.putExtra("enable long", mSettings[SETTING_LONG_RUN]);
+        intent.putExtra("enable pause", mSettings[SETTING_PAUSE]);
+        intent.putExtra("enable animate", mSettings[SETTING_ANIMATE]);
+        intent.putExtra("enable display", mSettings[SETTING_DISPLAY]);
+        intent.putExtra("resolution X", mRes.width);
+        intent.putExtra("resolution Y", mRes.height);
+        return intent;
+    }
+
+    public void btnRun(View v) {
+        IPTestList.TestName t[] = IPTestList.TestName.values();
+
+        int count = 0;
+        for (int i = 0; i < t.length; i++) {
+            if (mTestListView.isItemChecked(i)) {
+                count++;
+            }
+        }
+        if (count == 0) {
+            return;
+        }
+
+        int testList[] = new int[count];
+        count = 0;
+        for (int i = 0; i < t.length; i++) {
+            if (mTestListView.isItemChecked(i)) {
+                testList[count++] = i;
+            }
+        }
+
+        Intent intent = makeBasicLaunchIntent();
+        intent.putExtra("tests", testList);
+        startActivityForResult(intent, 0);
+    }
+
+    float rebase(float v, IPTestList.TestName t) {
+        if (v > 0.001) {
+            v = t.baseline / v;
+        }
+        float pr = (1920.f / mRes.width) * (1080.f / mRes.height);
+        return v / pr;
+    }
+
+    private void writeResults() {
+        // 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());
+            java.text.DecimalFormat df = new java.text.DecimalFormat("######.##");
+
+            for (int ct=0; ct < IPTestList.TestName.values().length; ct++) {
+                IPTestList.TestName t = IPTestList.TestName.values()[ct];
+                final float r = mResults[ct];
+                float r2 = rebase(r, t);
+                String s = new String("" + t.toString() + ", " + df.format(r) + ", " + df.format(r2));
+                rsWriter.write(s + "\n");
+            }
+            rsWriter.close();
+        } catch (IOException e) {
+            Log.v(TAG, "Unable to write result file " + e.getMessage());
+        }
+    }
+
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (requestCode == 0) {
+            if (resultCode == RESULT_OK) {
+                java.text.DecimalFormat df = new java.text.DecimalFormat("######.#");
+                mResults = new float[IPTestList.TestName.values().length];
+
+                float r[] = data.getFloatArrayExtra("results");
+                int id[] = data.getIntArrayExtra("tests");
+
+                for (int ct=0; ct < id.length; ct++) {
+                    IPTestList.TestName t = IPTestList.TestName.values()[id[ct]];
+
+                    String s = t.toString() + "   " + df.format(rebase(r[ct], t)) +
+                            "X,   " + df.format(r[ct]) + "ms";
+                    mTestList.set(id[ct], s);
+                    mTestListAdapter.notifyDataSetChanged();
+                    mResults[id[ct]] = r[ct];
+                }
+
+                double gm[] = {1.0, 1.0, 1.0};
+                double count[] = {0, 0, 0};
+                for (int ct=0; ct < IPTestList.TestName.values().length; ct++) {
+                    IPTestList.TestName t = IPTestList.TestName.values()[ct];
+                    gm[t.group] *= rebase(mResults[ct], t);
+                    count[t.group] += 1.0;
+                }
+                gm[0] = java.lang.Math.pow(gm[0], 1.0 / count[0]);
+                gm[1] = java.lang.Math.pow(gm[1], 1.0 / count[1]);
+                gm[2] = java.lang.Math.pow(gm[2], 1.0 / count[2]);
+
+                String s = "Results:  fp full=" + df.format(gm[0]) +
+                        ",  fp relaxed=" +df.format(gm[1]) +
+                        ",  intrinsics=" + df.format(gm[2]);
+                mResultView.setText(s);
+                writeResults();
+            }
+        }
+    }
+
+    public void btnSelAll(View v) {
+        IPTestList.TestName t[] = IPTestList.TestName.values();
+        for (int i=0; i < t.length; i++) {
+            mTestListView.setItemChecked(i, true);
+        }
+    }
+
+    public boolean onOptionsItemSelected(MenuItem item) {
+        // Handle presses on the action bar items
+        switch(item.getItemId()) {
+            case R.id.action_settings:
+                IPSettings newFragment = new IPSettings(mSettings);
+                newFragment.show(getFragmentManager(), "settings");
+                return true;
+            default:
+                return super.onOptionsItemSelected(item);
+        }
+    }
+
+    public void btnSelNone(View v) {
+        checkGroup(-1);
+    }
+
+    public void btnSelHp(View v) {
+        checkGroup(0);
+    }
+
+    public void btnSelLp(View v) {
+        checkGroup(1);
+    }
+
+    public void btnSettings(View v) {
+        IPSettings newFragment = new IPSettings(mSettings);
+        newFragment.show(getFragmentManager(), "settings");
+    }
+
+    public void btnSelIntrinsic(View v) {
+        checkGroup(2);
+    }
+
+
+
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/IPSettings.java b/java/tests/ImageProcessing2/src/com/android/rs/image/IPSettings.java
new file mode 100644
index 0000000..e73f542
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/IPSettings.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.image2;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.DialogFragment;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.view.View;
+
+public class IPSettings extends DialogFragment {
+    private boolean[] mEnables;
+    public boolean mOk = false;
+
+    public IPSettings(boolean[] enables) {
+        mEnables = enables;
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+        builder.setTitle(R.string.settings);
+
+        // Specify the list array, the items to be selected by default (null for none),
+        // and the listener through which to receive callbacks when items are selected
+        builder.setMultiChoiceItems(R.array.settings_array, mEnables,
+                          new DialogInterface.OnMultiChoiceClickListener() {
+                   @Override
+                   public void onClick(DialogInterface dialog, int which, boolean isChecked) {
+                       mEnables[which] = isChecked;
+                   }
+               });
+
+        // Set the action buttons
+        builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
+                   @Override
+                   public void onClick(DialogInterface dialog, int id) {
+                       mOk = true;
+                   }
+               });
+        builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+                   @Override
+                   public void onClick(DialogInterface dialog, int id) {
+                   }
+               });
+
+        return builder.create();
+    }
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/IPTestList.java b/java/tests/ImageProcessing2/src/com/android/rs/image/IPTestList.java
new file mode 100644
index 0000000..f2e7579
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/IPTestList.java
@@ -0,0 +1,196 @@
+/*
+ * 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 android.app.Activity;
+import android.view.View;
+import android.util.Log;
+
+public class IPTestList {
+    private final String TAG = "Img";
+    public final String RESULT_FILE = "image_processing_result.csv";
+
+    public static final int FULL_FP = 0;
+    public static final int RELAXED_FP = 1;
+    public static final int INTRINSIC = 2;
+
+    /**
+     * Define enum type for test names
+     */
+    public enum TestName {
+        LEVELS_VEC3_RELAXED ("Levels Vec3 Relaxed", RELAXED_FP, 61.1f),
+        LEVELS_VEC4_RELAXED ("Levels Vec4 Relaxed", RELAXED_FP, 44.6f),
+        LEVELS_VEC3_FULL ("Levels Vec3 Full", FULL_FP, 61.9f),
+        LEVELS_VEC4_FULL ("Levels Vec4 Full", FULL_FP, 73.f),
+        BLUR_RADIUS_25 ("Blur radius 25", RELAXED_FP, 1103.f),
+        INTRINSIC_BLUR_RADIUS_25 ("Intrinsic Blur radius 25", INTRINSIC, 176.f),
+        GREYSCALE ("Greyscale", RELAXED_FP, 43.7f),
+        GRAIN ("Grain", RELAXED_FP, 147.4f),
+        FISHEYE_FULL ("Fisheye Full", FULL_FP, 192.f),
+        FISHEYE_RELAXED ("Fisheye Relaxed", RELAXED_FP, 181.f),
+        FISHEYE_APPROXIMATE_FULL ("Fisheye Approximate Full", FULL_FP, 193.f),
+        FISHEYE_APPROXIMATE_RELAXED ("Fisheye Approximate Relaxed", RELAXED_FP, 183.f),
+        VIGNETTE_FULL ("Vignette Full", FULL_FP, 101.f),
+        VIGNETTE_RELAXED ("Vignette Relaxed", RELAXED_FP, 116.f),
+        VIGNETTE_APPROXIMATE_FULL ("Vignette Approximate Full", FULL_FP, 85.1f),
+        VIGNETTE_APPROXIMATE_RELAXED ("Vignette Approximate Relaxed", RELAXED_FP, 96.7f),
+        GROUP_TEST_EMULATED ("Group Test (emulated)", INTRINSIC, 51.7f),
+        GROUP_TEST_NATIVE ("Group Test (native)", INTRINSIC, 52.9f),
+        CONVOLVE_3X3 ("Convolve 3x3", RELAXED_FP, 74.2f),
+        INTRINSICS_CONVOLVE_3X3 ("Intrinsics Convolve 3x3", INTRINSIC, 33.3f),
+        COLOR_MATRIX ("ColorMatrix", RELAXED_FP, 33.8f),
+        INTRINSICS_COLOR_MATRIX ("Intrinsics ColorMatrix", INTRINSIC, 21.3f),
+        INTRINSICS_COLOR_MATRIX_GREY ("Intrinsics ColorMatrix Grey", INTRINSIC, 21.4f),
+        COPY ("Copy", RELAXED_FP, 21.4f),
+        CROSS_PROCESS_USING_LUT ("CrossProcess (using LUT)", INTRINSIC, 23.1f),
+        CONVOLVE_5X5 ("Convolve 5x5", RELAXED_FP, 236.f),
+        INTRINSICS_CONVOLVE_5X5 ("Intrinsics Convolve 5x5", INTRINSIC, 39.6f),
+        MANDELBROT_FLOAT ("Mandelbrot (fp32)", FULL_FP, 117.f),
+        MANDELBROT_DOUBLE ("Mandelbrot (fp64)", FULL_FP, 136.f),
+        INTRINSICS_BLEND ("Intrinsics Blend", INTRINSIC, 105.f),
+        INTRINSICS_BLUR_25G ("Intrinsics Blur 25 uchar", INTRINSIC, 37.8f),
+        VIBRANCE ("Vibrance", RELAXED_FP, 103.f),
+        BW_FILTER ("BW Filter", RELAXED_FP, 86.f),
+        SHADOWS ("Shadows", RELAXED_FP, 130.f),
+        CONTRAST ("Contrast", RELAXED_FP, 45.4f),
+        EXPOSURE ("Exposure", RELAXED_FP, 73.4f),
+        WHITE_BALANCE ("White Balance", RELAXED_FP, 138.2f),
+        COLOR_CUBE ("Color Cube", RELAXED_FP, 83.9f),
+        COLOR_CUBE_3D_INTRINSIC ("Color Cube (3D LUT intrinsic)", INTRINSIC, 34.7f),
+        ARTISTIC1 ("Artistic 1", RELAXED_FP, 140.f),
+        RESIZE_BI_SCRIPT ("Resize BiCubic Script", RELAXED_FP, 253.f),
+        RESIZE_BI_INTRINSIC ("Resize BiCubic Intrinsic", INTRINSIC, 255.f),
+        POSTERIZE_INVOKE ("Posterize with invoke", RELAXED_FP, 215.f),
+        POSTERIZE_SET ("Posterize with set", INTRINSIC, 221.f);
+
+
+        private final String name;
+        public final int group;
+        public final float baseline;
+
+        private TestName(String s, int g, float base) {
+            name = s;
+            group = g;
+            baseline = base;
+        }
+        private TestName(String s, int g) {
+            name = s;
+            group = g;
+            baseline = 1.f;
+        }
+
+        // return quoted string as displayed test name
+        public String toString() {
+            return name;
+        }
+    }
+
+    static TestBase newTest(TestName testName) {
+        switch(testName) {
+        case LEVELS_VEC3_RELAXED:
+            return new LevelsV4(false, false);
+        case LEVELS_VEC4_RELAXED:
+            return new LevelsV4(false, true);
+        case LEVELS_VEC3_FULL:
+            return new LevelsV4(true, false);
+        case LEVELS_VEC4_FULL:
+            return new LevelsV4(true, true);
+        case BLUR_RADIUS_25:
+            return new Blur25(false);
+        case INTRINSIC_BLUR_RADIUS_25:
+            return new Blur25(true);
+        case GREYSCALE:
+            return new Greyscale();
+        case GRAIN:
+            return new Grain();
+        case FISHEYE_FULL:
+            return new Fisheye(false, false);
+        case FISHEYE_RELAXED:
+            return new Fisheye(false, true);
+        case FISHEYE_APPROXIMATE_FULL:
+            return new Fisheye(true, false);
+        case FISHEYE_APPROXIMATE_RELAXED:
+            return new Fisheye(true, true);
+        case VIGNETTE_FULL:
+            return new Vignette(false, false);
+        case VIGNETTE_RELAXED:
+            return new Vignette(false, true);
+        case VIGNETTE_APPROXIMATE_FULL:
+            return new Vignette(true, false);
+        case VIGNETTE_APPROXIMATE_RELAXED:
+            return new Vignette(true, true);
+        case GROUP_TEST_EMULATED:
+            return new GroupTest(false);
+        case GROUP_TEST_NATIVE:
+            return new GroupTest(true);
+        case CONVOLVE_3X3:
+            return new Convolve3x3(false);
+        case INTRINSICS_CONVOLVE_3X3:
+            return new Convolve3x3(true);
+        case COLOR_MATRIX:
+            return new ColorMatrix(false, false);
+        case INTRINSICS_COLOR_MATRIX:
+            return new ColorMatrix(true, false);
+        case INTRINSICS_COLOR_MATRIX_GREY:
+            return new ColorMatrix(true, true);
+        case COPY:
+            return new Copy();
+        case CROSS_PROCESS_USING_LUT:
+            return new CrossProcess();
+        case CONVOLVE_5X5:
+            return new Convolve5x5(false);
+        case INTRINSICS_CONVOLVE_5X5:
+            return new Convolve5x5(true);
+        case MANDELBROT_FLOAT:
+            return new Mandelbrot(false);
+        case MANDELBROT_DOUBLE:
+            return new Mandelbrot(true);
+        case INTRINSICS_BLEND:
+            return new Blend();
+        case INTRINSICS_BLUR_25G:
+            return new Blur25G();
+        case VIBRANCE:
+            return new Vibrance();
+        case BW_FILTER:
+            return new BWFilter();
+        case SHADOWS:
+            return new Shadows();
+        case CONTRAST:
+            return new Contrast();
+        case EXPOSURE:
+            return new Exposure();
+        case WHITE_BALANCE:
+            return new WhiteBalance();
+        case COLOR_CUBE:
+            return new ColorCube(false);
+        case COLOR_CUBE_3D_INTRINSIC:
+            return new ColorCube(true);
+        case ARTISTIC1:
+            return new Artistic1();
+        case RESIZE_BI_SCRIPT:
+            return new Resize(false);
+        case RESIZE_BI_INTRINSIC:
+            return new Resize(true);
+        case POSTERIZE_INVOKE:
+            return new Posterize(true);
+        case POSTERIZE_SET:
+            return new Posterize(false);
+        }
+        return null;
+    }
+}
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java b/java/tests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java
index 4b0e2dd..0e133da 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java
@@ -17,13 +17,15 @@
 package com.android.rs.image2;
 
 import android.app.Activity;
+
+import android.content.Intent;
 import android.os.Bundle;
 import android.graphics.BitmapFactory;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.support.v8.renderscript.*;
-import android.view.SurfaceView;
-import android.view.SurfaceHolder;
+import android.os.Handler;
+import android.os.Message;
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
 import android.widget.ImageView;
@@ -31,89 +33,14 @@
 import android.widget.Spinner;
 import android.widget.TextView;
 import android.view.View;
-import android.util.Log;
-import java.lang.Math;
+import android.graphics.Point;
 
-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;
+import android.util.Log;
+
 
 public class ImageProcessingActivity2 extends Activity
                                        implements SeekBar.OnSeekBarChangeListener {
     private final String TAG = "Img";
-    public final String RESULT_FILE = "image_processing_result.csv";
-
-    RenderScript mRS;
-    Allocation mInPixelsAllocation;
-    Allocation mInPixelsAllocation2;
-    Allocation mOutPixelsAllocation;
-
-    /**
-     * Define enum type for test names
-     */
-    public enum TestName {
-        // totally there are 38 test cases
-        LEVELS_VEC3_RELAXED ("Levels Vec3 Relaxed"),
-        LEVELS_VEC4_RELAXED ("Levels Vec4 Relaxed"),
-        LEVELS_VEC3_FULL ("Levels Vec3 Full"),
-        LEVELS_VEC4_FULL ("Levels Vec4 Full"),
-        BLUR_RADIUS_25 ("Blur radius 25"),
-        INTRINSIC_BLUE_RADIUS_25 ("Intrinsic Blur radius 25"),
-        GREYSCALE ("Greyscale"),
-        GRAIN ("Grain"),
-        FISHEYE_FULL ("Fisheye Full"),
-        FISHEYE_RELAXED ("Fisheye Relaxed"),
-        FISHEYE_APPROXIMATE_FULL ("Fisheye Approximate Full"),
-        FISHEYE_APPROXIMATE_RELAXED ("Fisheye Approximate Relaxed"),
-        VIGNETTE_FULL ("Vignette Full"),
-        VIGNETTE_RELAXED ("Vignette Relaxed"),
-        VIGNETTE_APPROXIMATE_FULL ("Vignette Approximate Full"),
-        VIGNETTE_APPROXIMATE_RELAXED ("Vignette Approximate Relaxed"),
-        GROUP_TEST_EMULATED ("Group Test (emulated)"),
-        GROUP_TEST_NATIVE ("Group Test (native)"),
-        CONVOLVE_3X3 ("Convolve 3x3"),
-        INTRINSICS_CONVOLVE_3X3 ("Intrinsics Convolve 3x3"),
-        COLOR_MATRIX ("ColorMatrix"),
-        INTRINSICS_COLOR_MATRIX ("Intrinsics ColorMatrix"),
-        INTRINSICS_COLOR_MATRIX_GREY ("Intrinsics ColorMatrix Grey"),
-        COPY ("Copy"),
-        CROSS_PROCESS_USING_LUT ("CrossProcess (using LUT)"),
-        CONVOLVE_5X5 ("Convolve 5x5"),
-        INTRINSICS_CONVOLVE_5X5 ("Intrinsics Convolve 5x5"),
-        MANDELBROT ("Mandelbrot"),
-        INTRINSICS_BLEND ("Intrinsics Blend"),
-        INTRINSICS_BLUR_25G ("Intrinsics Blur 25 uchar"),
-        VIBRANCE ("Vibrance"),
-        BW_FILTER ("BW Filter"),
-        SHADOWS ("Shadows"),
-        CONTRAST ("Contrast"),
-        EXPOSURE ("Exposure"),
-        WHITE_BALANCE ("White Balance"),
-        COLOR_CUBE ("Color Cube"),
-        COLOR_CUBE_3D_INTRINSIC ("Color Cube (3D LUT intrinsic)");
-
-
-        private final String name;
-
-        private TestName(String s) {
-            name = s;
-        }
-
-        // return quoted string as displayed test name
-        public String toString() {
-            return name;
-        }
-    }
-
-    Bitmap mBitmapIn;
-    Bitmap mBitmapIn2;
-    Bitmap mBitmapOut;
 
     private Spinner mSpinner;
     private SeekBar mBar1;
@@ -121,47 +48,431 @@
     private SeekBar mBar3;
     private SeekBar mBar4;
     private SeekBar mBar5;
+
+    private int mBars[] = new int[5];
+    private int mBarsOld[] = new int[5];
+
     private TextView mText1;
     private TextView mText2;
     private TextView mText3;
     private TextView mText4;
     private TextView mText5;
-
-    private float mSaturation = 1.0f;
-
-    private TextView mBenchmarkResult;
-    private Spinner mTestSpinner;
-
-    private SurfaceView mSurfaceView;
     private ImageView mDisplayView;
 
+    private int mTestList[];
+    private float mTestResults[];
+
+    private boolean mToggleLong;
+    private boolean mTogglePause;
+    private boolean mToggleAnimate;
+    private boolean mToggleDisplay;
+    private int mBitmapWidth;
+    private int mBitmapHeight;
+    private boolean mDemoMode;
+
+    // Updates pending is a counter of how many kernels have been
+    // sent to RS for processing
+    //
+    // In benchmark this is incremented each time a kernel is launched and
+    // decremented each time a kernel completes
+    //
+    // In demo mode, each UI input increments the counter and it is zeroed
+    // when the latest settings are sent to RS for processing.
+    private int mUpdatesPending;
+
+    // In demo mode this is used to count updates in the pipeline.  It's
+    // incremented when work is submitted to RS and decremented when invalidate is
+    // called to display a result.
+    private int mShowsPending;
+
+
+
+    /////////////////////////////////////////////////////////////////////////
+
+    // Message processor to handle notifications for when kernel completes
+    private class MessageProcessor extends RenderScript.RSMessageHandler {
+        MessageProcessor() {
+        }
+
+        public void run() {
+            synchronized(mProcessor) {
+                // In demo mode, decrement the pending displays and notify the
+                // UI processor it can now enqueue more work if additional updates
+                // are blocked by a full pipeline.
+                if (mShowsPending > 0) {
+                    mShowsPending --;
+                    mProcessor.notifyAll();
+                    if (mToggleDisplay) {
+                        mProcessor.mHandler.sendMessage(Message.obtain());
+                    }
+                }
+            }
+        }
+    }
+
+
+    /////////////////////////////////////////////////////////////////////////
+    // Processor is a helper thread for running the work without
+    // blocking the UI thread.
+    class Processor extends Thread {
+        RenderScript mRS;
+        ScriptC_util mScriptUtils;
+        Allocation mInPixelsAllocation;
+        Allocation mInPixelsAllocation2;
+        Allocation mOutDisplayAllocation1;
+        Allocation mOutDisplayAllocation2;
+        Bitmap mBitmapOut1;
+        Bitmap mBitmapOut2;
+        int mActiveBitmap;
+
+        private float mLastResult;
+        private boolean mRun = true;
+        private boolean mDoingBenchmark;
+        private TestBase mTest;
+
+        private boolean mBenchmarkMode;
+
+        // We don't want to call the "changed" methods excessively as this
+        // can cause extra work for drivers.  Before running a test update
+        // any bars which have changed.
+        void runTest() {
+            if (mBars[0] != mBarsOld[0]) {
+                mTest.onBar1Changed(mBars[0]);
+                mBarsOld[0] = mBars[0];
+            }
+            if (mBars[1] != mBarsOld[1]) {
+                mTest.onBar2Changed(mBars[1]);
+                mBarsOld[1] = mBars[1];
+            }
+            if (mBars[2] != mBarsOld[2]) {
+                mTest.onBar3Changed(mBars[2]);
+                mBarsOld[2] = mBars[2];
+            }
+            if (mBars[3] != mBarsOld[3]) {
+                mTest.onBar4Changed(mBars[3]);
+                mBarsOld[3] = mBars[3];
+            }
+            if (mBars[4] != mBarsOld[4]) {
+                mTest.onBar5Changed(mBars[4]);
+                mBarsOld[4] = mBars[4];
+            }
+            mTest.runTest();
+        }
+
+        Processor(RenderScript rs, boolean benchmarkMode) {
+            mRS = rs;
+            mRS.setMessageHandler(new MessageProcessor());
+            mScriptUtils = new ScriptC_util(mRS);
+
+            switch(mBitmapWidth) {
+            case 1920:
+                mInPixelsAllocation = Allocation.createFromBitmapResource(
+                        mRS, getResources(), R.drawable.img1920x1080a);
+                mInPixelsAllocation2 = Allocation.createFromBitmapResource(
+                        mRS, getResources(), R.drawable.img1920x1080b);
+                mBitmapOut1 = Bitmap.createBitmap(1920, 1080, Bitmap.Config.ARGB_8888);
+                mBitmapOut2 = Bitmap.createBitmap(1920, 1080, Bitmap.Config.ARGB_8888);
+                break;
+            case 1280:
+                mInPixelsAllocation = Allocation.createFromBitmapResource(
+                        mRS, getResources(), R.drawable.img1280x720a);
+                mInPixelsAllocation2 = Allocation.createFromBitmapResource(
+                        mRS, getResources(), R.drawable.img1280x720b);
+                mBitmapOut1 = Bitmap.createBitmap(1280, 720, Bitmap.Config.ARGB_8888);
+                mBitmapOut2 = Bitmap.createBitmap(1280, 720, Bitmap.Config.ARGB_8888);
+                break;
+            case 800:
+                mInPixelsAllocation = Allocation.createFromBitmapResource(
+                        mRS, getResources(), R.drawable.img800x450a);
+                mInPixelsAllocation2 = Allocation.createFromBitmapResource(
+                        mRS, getResources(), R.drawable.img800x450b);
+                mBitmapOut1 = Bitmap.createBitmap(800, 450, Bitmap.Config.ARGB_8888);
+                mBitmapOut2 = Bitmap.createBitmap(800, 450, Bitmap.Config.ARGB_8888);
+                break;
+            }
+
+            mBitmapOut1.setHasAlpha(false);
+            mBitmapOut2.setHasAlpha(false);
+            mOutDisplayAllocation1 = Allocation.createFromBitmap(mRS, mBitmapOut1);
+            mOutDisplayAllocation2 = Allocation.createFromBitmap(mRS, mBitmapOut2);
+            mBenchmarkMode = benchmarkMode;
+            start();
+        }
+
+        class Result {
+            float totalTime;
+            int itterations;
+        }
+
+        // Run one loop of kernels for at least the specified minimum time.
+        // The function returns the average time in ms for the test run
+        private Result runBenchmarkLoop(float minTime) {
+            mUpdatesPending = 0;
+            Result r = new Result();
+
+            long t = java.lang.System.currentTimeMillis();
+            do {
+                synchronized(this) {
+                    // Shows pending is used to track the number of kernels in the RS pipeline
+                    // We throttle it to 2.  This provide some buffering to allow a kernel to be started
+                    // before we are nofitied the previous finished.  However, larger numbers are uncommon
+                    // in interactive apps as they introduce 'lag' between user input and display.
+                    mShowsPending++;
+                    if (mShowsPending > 2) {
+                        try {
+                            this.wait();
+                        } catch(InterruptedException e) {
+                        }
+                    }
+                }
+
+                // If animations are enabled update the test state.
+                if (mToggleAnimate) {
+                    mTest.animateBars(r.totalTime);
+                }
+
+                // Run the kernel
+                if (mActiveBitmap == 0) {
+                    mTest.mOutPixelsAllocation = mOutDisplayAllocation1;
+                } else {
+                    mTest.mOutPixelsAllocation = mOutDisplayAllocation2;
+                }
+                mTest.runTest();
+                r.itterations ++;
+
+                if (mToggleDisplay) {
+                    if (mActiveBitmap == 0) {
+                        mOutDisplayAllocation1.copyTo(mBitmapOut1);
+                    } else {
+                        mOutDisplayAllocation2.copyTo(mBitmapOut2);
+                    }
+                }
+
+                // Send our RS message handler a message so we know when this work has completed
+                //mRS.sendMessage(mActiveBitmap, null);
+                mScriptUtils.invoke_utilSendMessage(mActiveBitmap);
+                mActiveBitmap ^= 1;
+
+                long t2 = java.lang.System.currentTimeMillis();
+                r.totalTime += (t2 - t) / 1000.f;
+                t = t2;
+            } while (r.totalTime < minTime);
+
+            // Wait for any stray operations to complete and update the final time
+            mRS.finish();
+            long t2 = java.lang.System.currentTimeMillis();
+            r.totalTime += (t2 - t) / 1000.f;
+            t = t2;
+            return r;
+        }
+
+
+        // Get a benchmark result for a specific test
+        private float getBenchmark() {
+            mDoingBenchmark = true;
+            mUpdatesPending = 0;
+
+            long result = 0;
+            float runtime = 1.f;
+            if (mToggleLong) {
+                runtime = 10.f;
+            }
+
+            // We run a short bit of work before starting the actual test
+            // this is to let any power management do its job and respond
+            runBenchmarkLoop(0.3f);
+
+            // Run the actual benchmark
+            Result r = runBenchmarkLoop(runtime);
+
+            Log.v("rs", "Test: time=" + r.totalTime +"s,  frames=" + r.itterations +
+                  ", avg=" + r.totalTime / r.itterations * 1000.f);
+
+            mDoingBenchmark = false;
+            return r.totalTime / r.itterations * 1000.f;
+        }
+
+        private int mDisplayedBitmap;
+        private Handler mHandler = new Handler() {
+            @Override
+            public void handleMessage(Message msg) {
+                if (mDisplayedBitmap == 0) {
+                    mDisplayView.setImageBitmap(mBitmapOut1);
+                } else {
+                    mDisplayView.setImageBitmap(mBitmapOut2);
+                }
+                mDisplayedBitmap ^= 1;
+                mDisplayView.invalidate();
+            }
+        };
+
+        public void run() {
+            while (mRun) {
+                // Our loop for launching tests or benchmarks
+                synchronized(this) {
+                    // If we have no work to do, or we have displays pending, wait
+                    if ((mUpdatesPending == 0) || (mShowsPending != 0)) {
+                        try {
+                            this.wait();
+                        } catch(InterruptedException e) {
+                        }
+                    }
+
+                    // We may have been asked to exit while waiting
+                    if (!mRun) return;
+                }
+
+                if (mBenchmarkMode) {
+                    // Loop over the tests we want to benchmark
+                    for (int ct=0; (ct < mTestList.length) && mRun; ct++) {
+
+                        // For reproducibility we wait a short time for any sporadic work
+                        // created by the user touching the screen to launch the test to pass.
+                        // Also allows for things to settle after the test changes.
+                        mRS.finish();
+                        try {
+                            sleep(250);
+                        } catch(InterruptedException e) {
+                        }
+
+                        // If we just ran a test, we destroy it here to relieve some memory pressure
+                        if (mTest != null) {
+                            mTest.destroy();
+                        }
+
+                        // Select the next test
+                        mTest = changeTest(mTestList[ct], false);
+
+                        // If the user selected the "long pause" option, wait
+                        if (mTogglePause) {
+                            for (int i=0; (i < 100) && mRun; i++) {
+                                try {
+                                    sleep(100);
+                                } catch(InterruptedException e) {
+                                }
+                            }
+                        }
+
+                        // Run the test
+                        mTestResults[ct] = getBenchmark();
+                    }
+                    onBenchmarkFinish(mRun);
+                    return;
+                } else {
+                    boolean update = false;
+                    synchronized(this) {
+                        // If we have updates to process and are not blocked by pending shows,
+                        // start the next kernel
+                        if ((mUpdatesPending > 0) && (mShowsPending == 0)) {
+                            mUpdatesPending = 0;
+                            update = true;
+                            mShowsPending++;
+                        }
+                    }
+
+                    if (update) {
+                        // Run the kernel
+                        if (mActiveBitmap == 0) {
+                            mTest.mOutPixelsAllocation = mOutDisplayAllocation1;
+                        } else {
+                            mTest.mOutPixelsAllocation = mOutDisplayAllocation2;
+                        }
+                        runTest();
+
+                        if (mToggleDisplay) {
+                            if (mActiveBitmap == 0) {
+                                mOutDisplayAllocation1.copyTo(mBitmapOut1);
+                            } else {
+                                mOutDisplayAllocation2.copyTo(mBitmapOut2);
+                            }
+                        }
+
+                        // Send our RS message handler a message so we know when this work has completed
+                        //mRS.sendMessage(mActiveBitmap, null);
+                        mScriptUtils.invoke_utilSendMessage(mActiveBitmap);
+                        mActiveBitmap ^= 1;
+                    }
+                }
+            }
+
+        }
+
+        public void update() {
+            // something UI related has changed, enqueue an update if one is not
+            // already pending.  Wake the worker if needed
+            synchronized(this) {
+                if (mUpdatesPending < 2) {
+                    mUpdatesPending++;
+                    notifyAll();
+                }
+            }
+        }
+
+        public void exit() {
+            mRun = false;
+
+            synchronized(this) {
+                notifyAll();
+            }
+
+            try {
+                this.join();
+            } catch(InterruptedException e) {
+            }
+
+            mInPixelsAllocation.destroy();
+            mInPixelsAllocation2.destroy();
+
+            if (mTest != null) {
+                mTest.destroy();
+                mTest = null;
+            }
+            mOutDisplayAllocation1.destroy();
+            mOutDisplayAllocation2.destroy();
+            mRS.destroy();
+
+            mInPixelsAllocation = null;
+            mInPixelsAllocation2 = null;
+            mOutDisplayAllocation1 = null;
+            mOutDisplayAllocation2 = null;
+            mRS = null;
+        }
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////////
+
     private boolean mDoingBenchmark;
+    public Processor mProcessor;
 
-    private TestBase mTest;
-    private int mRunCount;
+    TestBase changeTest(IPTestList.TestName t, boolean setupUI) {
+        TestBase tb = IPTestList.newTest(t);
 
-    public void updateDisplay() {
-            mTest.updateBitmap(mBitmapOut);
-            mDisplayView.invalidate();
+        tb.createBaseTest(this);
+        if (setupUI) {
+            setupBars(tb);
+        }
+        return tb;
+    }
+
+    TestBase changeTest(int id, boolean setupUI) {
+        IPTestList.TestName t = IPTestList.TestName.values()[id];
+        return changeTest(t, setupUI);
     }
 
     public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
         if (fromUser) {
-
             if (seekBar == mBar1) {
-                mTest.onBar1Changed(progress);
+                mBars[0] = progress;
             } else if (seekBar == mBar2) {
-                mTest.onBar2Changed(progress);
+                mBars[1] = progress;
             } else if (seekBar == mBar3) {
-                mTest.onBar3Changed(progress);
+                mBars[2] = progress;
             } else if (seekBar == mBar4) {
-                mTest.onBar4Changed(progress);
+                mBars[3] = progress;
             } else if (seekBar == mBar5) {
-                mTest.onBar5Changed(progress);
+                mBars[4] = progress;
             }
-
-            mTest.runTest();
-            updateDisplay();
+            mProcessor.update();
         }
     }
 
@@ -171,191 +482,57 @@
     public void onStopTrackingTouch(SeekBar seekBar) {
     }
 
-    void setupBars() {
+    void setupBars(TestBase t) {
         mSpinner.setVisibility(View.VISIBLE);
-        mTest.onSpinner1Setup(mSpinner);
+        t.onSpinner1Setup(mSpinner);
 
         mBar1.setVisibility(View.VISIBLE);
         mText1.setVisibility(View.VISIBLE);
-        mTest.onBar1Setup(mBar1, mText1);
+        t.onBar1Setup(mBar1, mText1);
 
         mBar2.setVisibility(View.VISIBLE);
         mText2.setVisibility(View.VISIBLE);
-        mTest.onBar2Setup(mBar2, mText2);
+        t.onBar2Setup(mBar2, mText2);
 
         mBar3.setVisibility(View.VISIBLE);
         mText3.setVisibility(View.VISIBLE);
-        mTest.onBar3Setup(mBar3, mText3);
+        t.onBar3Setup(mBar3, mText3);
 
         mBar4.setVisibility(View.VISIBLE);
         mText4.setVisibility(View.VISIBLE);
-        mTest.onBar4Setup(mBar4, mText4);
+        t.onBar4Setup(mBar4, mText4);
 
         mBar5.setVisibility(View.VISIBLE);
         mText5.setVisibility(View.VISIBLE);
-        mTest.onBar5Setup(mBar5, mText5);
+        t.onBar5Setup(mBar5, mText5);
     }
 
+    void hideBars() {
+        mSpinner.setVisibility(View.INVISIBLE);
 
-    void changeTest(TestName testName) {
-        if (mTest != null) {
-            mTest.destroy();
-        }
-        switch(testName) {
-        case LEVELS_VEC3_RELAXED:
-            mTest = new LevelsV4(false, false);
-            break;
-        case LEVELS_VEC4_RELAXED:
-            mTest = new LevelsV4(false, true);
-            break;
-        case LEVELS_VEC3_FULL:
-            mTest = new LevelsV4(true, false);
-            break;
-        case LEVELS_VEC4_FULL:
-            mTest = new LevelsV4(true, true);
-            break;
-        case BLUR_RADIUS_25:
-            mTest = new Blur25(false);
-            break;
-        case INTRINSIC_BLUE_RADIUS_25:
-            mTest = new Blur25(true);
-            break;
-        case GREYSCALE:
-            mTest = new Greyscale();
-            break;
-        case GRAIN:
-            mTest = new Grain();
-            break;
-        case FISHEYE_FULL:
-            mTest = new Fisheye(false, false);
-            break;
-        case FISHEYE_RELAXED:
-            mTest = new Fisheye(false, true);
-            break;
-        case FISHEYE_APPROXIMATE_FULL:
-            mTest = new Fisheye(true, false);
-            break;
-        case FISHEYE_APPROXIMATE_RELAXED:
-            mTest = new Fisheye(true, true);
-            break;
-        case VIGNETTE_FULL:
-            mTest = new Vignette(false, false);
-            break;
-        case VIGNETTE_RELAXED:
-            mTest = new Vignette(false, true);
-            break;
-        case VIGNETTE_APPROXIMATE_FULL:
-            mTest = new Vignette(true, false);
-            break;
-        case VIGNETTE_APPROXIMATE_RELAXED:
-            mTest = new Vignette(true, true);
-            break;
-        case GROUP_TEST_EMULATED:
-            mTest = new GroupTest(false);
-            break;
-        case GROUP_TEST_NATIVE:
-            mTest = new GroupTest(true);
-            break;
-        case CONVOLVE_3X3:
-            mTest = new Convolve3x3(false);
-            break;
-        case INTRINSICS_CONVOLVE_3X3:
-            mTest = new Convolve3x3(true);
-            break;
-        case COLOR_MATRIX:
-            mTest = new ColorMatrix(false, false);
-            break;
-        case INTRINSICS_COLOR_MATRIX:
-            mTest = new ColorMatrix(true, false);
-            break;
-        case INTRINSICS_COLOR_MATRIX_GREY:
-            mTest = new ColorMatrix(true, true);
-            break;
-        case COPY:
-            mTest = new Copy();
-            break;
-        case CROSS_PROCESS_USING_LUT:
-            mTest = new CrossProcess();
-            break;
-        case CONVOLVE_5X5:
-            mTest = new Convolve5x5(false);
-            break;
-        case INTRINSICS_CONVOLVE_5X5:
-            mTest = new Convolve5x5(true);
-            break;
-        case MANDELBROT:
-            mTest = new Mandelbrot();
-            break;
-        case INTRINSICS_BLEND:
-            mTest = new Blend();
-            break;
-        case INTRINSICS_BLUR_25G:
-            mTest = new Blur25G();
-            break;
-        case VIBRANCE:
-            mTest = new Vibrance();
-            break;
-        case BW_FILTER:
-            mTest = new BWFilter();
-            break;
-        case SHADOWS:
-            mTest = new Shadows();
-            break;
-        case CONTRAST:
-            mTest = new Contrast();
-            break;
-        case EXPOSURE:
-            mTest = new Exposure();
-            break;
-        case WHITE_BALANCE:
-            mTest = new WhiteBalance();
-            break;
-        case COLOR_CUBE:
-            mTest = new ColorCube(false);
-            break;
-        case COLOR_CUBE_3D_INTRINSIC:
-            mTest = new ColorCube(true);
-            break;
-        }
+        mBar1.setVisibility(View.INVISIBLE);
+        mText1.setVisibility(View.INVISIBLE);
 
-        mTest.createBaseTest(this, mBitmapIn, mBitmapIn2, mBitmapOut);
-        setupBars();
+        mBar2.setVisibility(View.INVISIBLE);
+        mText2.setVisibility(View.INVISIBLE);
 
-        mTest.runTest();
-        updateDisplay();
-        mBenchmarkResult.setText("Result: not run");
+        mBar3.setVisibility(View.INVISIBLE);
+        mText3.setVisibility(View.INVISIBLE);
+
+        mBar4.setVisibility(View.INVISIBLE);
+        mText4.setVisibility(View.INVISIBLE);
+
+        mBar5.setVisibility(View.INVISIBLE);
+        mText5.setVisibility(View.INVISIBLE);
     }
 
-    void setupTests() {
-        mTestSpinner.setAdapter(new ArrayAdapter<TestName>(
-            this, R.layout.spinner_layout, TestName.values()));
-    }
-
-    private AdapterView.OnItemSelectedListener mTestSpinnerListener =
-            new AdapterView.OnItemSelectedListener() {
-                public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
-                    changeTest(TestName.values()[pos]);
-                }
-
-                public void onNothingSelected(AdapterView parent) {
-
-                }
-            };
-
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
 
-        mBitmapIn = loadBitmap(R.drawable.img1600x1067);
-        mBitmapIn2 = loadBitmap(R.drawable.img1600x1067b);
-        mBitmapOut = Bitmap.createBitmap(mBitmapIn.getWidth(), mBitmapIn.getHeight(),
-                                         mBitmapIn.getConfig());
-
-        mSurfaceView = (SurfaceView) findViewById(R.id.surface);
-
         mDisplayView = (ImageView) findViewById(R.id.display);
-        mDisplayView.setImageBitmap(mBitmapOut);
+        //mDisplayView.setImageBitmap(mBitmapOut);
 
         mSpinner = (Spinner) findViewById(R.id.spinner1);
 
@@ -376,95 +553,83 @@
         mText3 = (TextView) findViewById(R.id.slider3Text);
         mText4 = (TextView) findViewById(R.id.slider4Text);
         mText5 = (TextView) findViewById(R.id.slider5Text);
-
-        mTestSpinner = (Spinner) findViewById(R.id.filterselection);
-        mTestSpinner.setOnItemSelectedListener(mTestSpinnerListener);
-
-        mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText);
-        mBenchmarkResult.setText("Result: not run");
-
-
-        mRS = RenderScript.create(this);
-        mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn);
-        mInPixelsAllocation2 = Allocation.createFromBitmap(mRS, mBitmapIn2);
-        mOutPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapOut);
-
-
-        setupTests();
-        changeTest(TestName.LEVELS_VEC3_RELAXED);
     }
 
-
-    private Bitmap loadBitmap(int resource) {
-        final BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
-        return BitmapFactory.decodeResource(getResources(), resource, options);
+    @Override
+    protected void onPause() {
+        super.onPause();
+        mProcessor.exit();
     }
 
-    // button hook
-    public void benchmark(View v) {
-        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;
+    public void onBenchmarkFinish(boolean ok) {
+        if (ok) {
+            Intent intent = new Intent();
+            intent.putExtra("tests", mTestList);
+            intent.putExtra("results", mTestResults);
+            setResult(RESULT_OK, intent);
+        } else {
+            setResult(RESULT_CANCELED);
         }
-        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 (TestName tn: TestName.values()) {
-                changeTest(tn);
-                float t = getBenchmark();
-                String s = new String("" + tn.toString() + ", " + t);
-                rsWriter.write(s + "\n");
-                Log.v(TAG, "Test " + s + "ms\n");
+        finish();
+    }
+
+
+    void startProcessor() {
+        if (!mDemoMode) {
+            hideBars();
+        }
+
+        Point size = new Point();
+        getWindowManager().getDefaultDisplay().getSize(size);
+
+        int mScreenWidth = size.x;
+        int mScreenHeight = size.y;
+
+        int tw = mBitmapWidth;
+        int th = mBitmapHeight;
+
+        if (tw > mScreenWidth || th > mScreenHeight) {
+            float s1 = (float)tw / (float)mScreenWidth;
+            float s2 = (float)th / (float)mScreenHeight;
+
+            if (s1 > s2) {
+                tw /= s1;
+                th /= s1;
+            } else {
+                tw /= s2;
+                th /= s2;
             }
-            rsWriter.close();
-        } catch (IOException e) {
-            Log.v(TAG, "Unable to write result file " + e.getMessage());
         }
-        changeTest(TestName.LEVELS_VEC3_RELAXED);
+
+        android.util.Log.v("rs", "TV sizes " + tw + ", " + th);
+
+        mProcessor = new Processor(RenderScript.create(this), !mDemoMode);
+        if (mDemoMode) {
+            mProcessor.mTest = changeTest(mTestList[0], true);
+        }
+        mProcessor.update();
     }
 
-    // For benchmark test
-    public float getBenchmark() {
-        mDoingBenchmark = true;
+    @Override
+    protected void onResume() {
+        super.onResume();
+        Intent i = getIntent();
+        mTestList = i.getIntArrayExtra("tests");
+        mToggleLong = i.getBooleanExtra("enable long", false);
+        mTogglePause = i.getBooleanExtra("enable pause", false);
+        mToggleAnimate = i.getBooleanExtra("enable animate", false);
+        mToggleDisplay = i.getBooleanExtra("enable display", false);
+        mBitmapWidth = i.getIntExtra("resolution X", 0);
+        mBitmapHeight = i.getIntExtra("resolution Y", 0);
+        mDemoMode = i.getBooleanExtra("demo", false);
 
-        mTest.setupBenchmark();
-        long result = 0;
+        mTestResults = new float[mTestList.length];
 
-        //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");
-        int ct = 0;
-        t = java.lang.System.currentTimeMillis();
-        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;
-
-        mTest.exitBenchmark();
-        mDoingBenchmark = false;
-
-        return ft;
+        startProcessor();
     }
+
+    protected void onDestroy() {
+        super.onDestroy();
+    }
+
 }
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/LevelsV4.java b/java/tests/ImageProcessing2/src/com/android/rs/image/LevelsV4.java
index 199c504..1f2dd60 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/LevelsV4.java
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/LevelsV4.java
@@ -103,7 +103,7 @@
     public boolean onBar4Setup(SeekBar b, TextView t) {
         b.setMax(128);
         b.setProgress(128);
-        t.setText("Out White");
+        t.setText("In White");
         return true;
     }
     public boolean onBar5Setup(SeekBar b, TextView t) {
@@ -134,6 +134,12 @@
         setLevels();
     }
 
+    public void animateBars(float time) {
+        mSaturation = time % 2.f;
+        setSaturation();
+    }
+
+
     public void createTest(android.content.res.Resources res) {
         mScriptR = new ScriptC_levels_relaxed(mRS);
         mScriptF = new ScriptC_levels_full(mRS);
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.java
index f957df4..e2c23a1 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.java
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.java
@@ -24,6 +24,11 @@
 
 public class Mandelbrot extends TestBase {
     private ScriptC_mandelbrot mScript;
+    private boolean mUseDouble = false;
+
+    public Mandelbrot(boolean useDouble) {
+        mUseDouble = useDouble;
+    }
 
     public boolean onBar1Setup(SeekBar b, TextView t) {
         t.setText("Iterations");
@@ -84,7 +89,11 @@
     }
 
     public void runTest() {
-        mScript.forEach_root(mOutPixelsAllocation);
+        if (mUseDouble) {
+            mScript.forEach_rootD(mOutPixelsAllocation);
+        } else {
+            mScript.forEach_root(mOutPixelsAllocation);
+        }
         mRS.finish();
     }
 
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Posterize.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Posterize.java
new file mode 100644
index 0000000..fb1867e
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Posterize.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.image2;
+
+import android.support.v8.renderscript.*;
+
+public class Posterize extends TestBase {
+    private ScriptC_posterize mScript;
+    boolean mUseInvokes;
+
+    Posterize(boolean useInvoke) {
+        mUseInvokes = useInvoke;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_posterize(mRS);
+    }
+
+    void setParams(float intensHigh, float intensLow, int r, int g, int b) {
+        if (mUseInvokes) {
+            mScript.invoke_setParams(intensHigh, intensLow,
+                                     (short)r, (short)g, (short)b);
+        } else {
+            mScript.set_intensityLow(intensLow);
+            mScript.set_intensityHigh(intensHigh);
+            mScript.set_color(new Short4((short)r, (short)g, (short)b, (short)255));
+        }
+    }
+
+    public void runTest() {
+        mScript.set_inputImage(mInPixelsAllocation);
+        setParams(.2f, 0.f, 255, 0, 0);
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+        setParams(.4f, 0.2f, 0, 255, 0);
+        mScript.forEach_root(mOutPixelsAllocation, mOutPixelsAllocation);
+        setParams(.6f, 0.4f, 0, 0, 255);
+        mScript.forEach_root(mOutPixelsAllocation, mOutPixelsAllocation);
+        setParams(.8f, 0.6f, 255, 255, 0);
+        mScript.forEach_root(mOutPixelsAllocation, mOutPixelsAllocation);
+        setParams(1.0f, 0.8f, 0, 255, 255);
+        mScript.forEach_root(mOutPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Resize.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Resize.java
new file mode 100644
index 0000000..4353324
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Resize.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.image2;
+
+import android.support.v8.renderscript.*;
+
+
+public class Resize extends TestBase {
+    private ScriptC_resize mScript;
+
+    private Allocation mScratchAllocation;
+    private int mWidth;
+    private int mHeight;
+
+    public Resize(boolean useIntrinsic) {
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mWidth = mInPixelsAllocation.getType().getX();
+        mHeight = mInPixelsAllocation.getType().getY();
+        float scale = 1.f / 32.f;
+
+        Type.Builder tb = new Type.Builder(mRS, mInPixelsAllocation.getElement());
+        tb.setX((int)(mWidth * scale));
+        tb.setY((int)(mHeight * scale));
+        Type t = tb.create();
+        mScratchAllocation = Allocation.createTyped(mRS, t);
+
+        // make small buffer
+        mScript = new ScriptC_resize(mRS);
+        mScript.set_gIn(mInPixelsAllocation);
+        mScript.set_gWidthIn(mWidth);
+        mScript.set_gHeightIn(mHeight);
+        mScript.set_scale(1.f / scale);
+        mScript.forEach_nearest(mScratchAllocation);
+
+        // setup normal ops
+        mScript.set_gIn(mScratchAllocation);
+        mScript.set_gWidthIn(t.getX());
+        mScript.set_gHeightIn(t.getY());
+        mScript.set_scale(scale);
+    }
+
+    public void runTest() {
+        mScript.forEach_bicubic(mOutPixelsAllocation);
+    }
+
+}
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/TestBase.java b/java/tests/ImageProcessing2/src/com/android/rs/image/TestBase.java
index eeabc73..240239d 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/TestBase.java
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/TestBase.java
@@ -18,19 +18,12 @@
 
 import android.app.Activity;
 import android.content.Context;
-import android.os.Bundle;
-import android.graphics.BitmapFactory;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
 import android.support.v8.renderscript.*;
-import android.view.SurfaceView;
-import android.view.SurfaceHolder;
 import android.widget.ImageView;
 import android.widget.SeekBar;
 import android.widget.TextView;
 import android.view.View;
 import android.util.Log;
-import java.lang.Math;
 import android.widget.Spinner;
 
 public class TestBase  {
@@ -40,7 +33,6 @@
     protected Allocation mInPixelsAllocation;
     protected Allocation mInPixelsAllocation2;
     protected Allocation mOutPixelsAllocation;
-
     protected ImageProcessingActivity2 act;
 
     // Override to use UI elements
@@ -83,18 +75,21 @@
         return false;
     }
 
+    public void animateBars(float time) {
+    }
+
     public boolean onSpinner1Setup(Spinner s) {
         s.setVisibility(View.INVISIBLE);
         return false;
     }
 
-    public final void createBaseTest(ImageProcessingActivity2 ipact, Bitmap b, Bitmap b2, Bitmap outb) {
+    public final void createBaseTest(ImageProcessingActivity2 ipact) {
         act = ipact;
-        mRS = ipact.mRS;
+        mRS = ipact.mProcessor.mRS;
 
-        mInPixelsAllocation = ipact.mInPixelsAllocation;
-        mInPixelsAllocation2 = ipact.mInPixelsAllocation2;
-        mOutPixelsAllocation = ipact.mOutPixelsAllocation;
+        mInPixelsAllocation = ipact.mProcessor.mInPixelsAllocation;
+        mInPixelsAllocation2 = ipact.mProcessor.mInPixelsAllocation2;
+        mOutPixelsAllocation = ipact.mProcessor.mOutDisplayAllocation1;
 
         createTest(act.getResources());
     }
@@ -107,22 +102,6 @@
     public void runTest() {
     }
 
-    public void finish() {
-        mRS.finish();
-    }
-
     public void destroy() {
     }
-
-    public void updateBitmap(Bitmap b) {
-        mOutPixelsAllocation.copyTo(b);
-    }
-
-    // Override to configure specific benchmark config.
-    public void setupBenchmark() {
-    }
-
-    // Override to reset after benchmark.
-    public void exitBenchmark() {
-    }
 }
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/Vignette.java b/java/tests/ImageProcessing2/src/com/android/rs/image/Vignette.java
index e24c548..4f00304 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/Vignette.java
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/Vignette.java
@@ -68,6 +68,7 @@
         return true;
     }
 
+
     public void onBar1Changed(int progress) {
         scale = progress / 50.0f;
         do_init();
@@ -89,6 +90,11 @@
         do_init();
     }
 
+    public void animateBars(float time) {
+        scale = time % 2.f;
+        do_init();
+    }
+
     private void do_init() {
         if (approx) {
             if (relaxed)
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/WhiteBalance.java b/java/tests/ImageProcessing2/src/com/android/rs/image/WhiteBalance.java
index 658e3b1..50aa5a2 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/WhiteBalance.java
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/WhiteBalance.java
@@ -18,7 +18,6 @@
 
 import java.lang.Math;
 
-import android.support.v8.renderscript.*;
 
 public class WhiteBalance extends TestBase {
     private ScriptC_wbalance mScript;
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/artistic1.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/artistic1.rs
new file mode 100644
index 0000000..2869e16
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/artistic1.rs
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+#pragma rs_fp_relaxed
+
+rs_allocation gBlur;
+
+static float gOverWm1;
+static float gOverHm1;
+static uchar gLutR[256];
+static uchar gLutG[256];
+static uchar gLutB[256];
+
+void setup() {
+    int w = rsAllocationGetDimX(gBlur);
+    int h = rsAllocationGetDimY(gBlur);
+    gOverWm1 = 1.f / w;
+    gOverHm1 = 1.f / h;
+
+    for (int x=0; x < 256; x++) {
+        gLutR[x] = x;//255-x;
+        gLutG[x] = x;//255-x;
+        gLutB[x] = x;//255-x;
+    }
+}
+
+uchar4 RS_KERNEL process(uchar4 in, uint32_t x, uint32_t y) {
+    float2 xyDist;
+    xyDist.x = (x * gOverWm1 - 0.5f);
+    xyDist.y = (y * gOverHm1 - 0.5f);
+
+    // color
+    float4 v1 = rsUnpackColor8888(in);
+    float4 v2 = rsUnpackColor8888(rsGetElementAt_uchar4(gBlur, x, y));
+
+    float dist = dot(xyDist, xyDist) * 1.4f;
+    float pdist = native_powr(dist, 2.7f * 0.5f);
+    //float pdist = powr(dist, 2.7f * 0.5f);
+
+    pdist = clamp(pdist, 0.f, 1.f);
+    v1 = mix(v1, v2, dist * 2.f);
+    v1 *= 1.f - pdist;
+
+    // apply curve
+    uchar4 out = rsPackColorTo8888(v1);
+
+    out.r = gLutR[out.r];
+    out.g = gLutG[out.g];
+    out.b = gLutB[out.b];
+    return out;
+}
+
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/blend.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/blend.rs
index 9ec1246..96dfc96 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/blend.rs
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/blend.rs
@@ -13,11 +13,14 @@
 // limitations under the License.
 
 #include "ip.rsh"
+#pragma rs_fp_relaxed
 
 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;
+uchar4 RS_KERNEL setImageAlpha(uchar4 in, uint32_t x, uint32_t y) {
+    uchar4 out;
+    out.rgba = convert_uchar4((convert_uint4(in.rgba) * alpha) >> (uint4)8);
+    out.a = alpha;
+    return out;
 }
 
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/bwfilter.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/bwfilter.rs
index e706d44..e211620 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/bwfilter.rs
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/bwfilter.rs
@@ -15,7 +15,7 @@
  */
 
 #include "ip.rsh"
-//#pragma rs_fp_relaxed
+#pragma rs_fp_relaxed
 
 static float sr = 0.f;
 static float sg = 0.f;
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/colorcube.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/colorcube.rs
index c0d6ace..dbdd2f6 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/colorcube.rs
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/colorcube.rs
@@ -32,15 +32,10 @@
 
     float4 m = (float4)(1.f / 255.f) * convert_float4(gDims - 1);
     gCoordMul = convert_int4(m * (float4)0x10000);
-
-    rsDebug("dims", gDims);
-    rsDebug("gCoordMul", gCoordMul);
 }
 
-void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
-    //rsDebug("root", in);
-
-    int4 baseCoord = convert_int4(*in) * gCoordMul;
+uchar4 RS_KERNEL root(uchar4 in) {
+    int4 baseCoord = convert_int4(in) * gCoordMul;
     int4 coord1 = baseCoord >> (int4)16;
     int4 coord2 = min(coord1 + 1, gDims - 1);
 
@@ -67,23 +62,8 @@
     uint4 v = ((z0 * weight1.z) + (z1 * weight2.z)) >> (uint4)16;
     uint4 v2 = (v + 0x7f) >> (uint4)8;
 
-    *out = convert_uchar4(v2);
-    out->a = 0xff;
-
-    #if 0
-    if (in->r != out->r) {
-        rsDebug("dr", in->r - out->r);
-        //rsDebug("in", convert_int4(*in));
-        //rsDebug("coord1", coord1);
-        //rsDebug("coord2", coord2);
-        //rsDebug("weight1", weight1);
-        //rsDebug("weight2", weight2);
-        //rsDebug("yz00", yz00);
-        //rsDebug("z0", z0);
-        //rsDebug("v", v);
-        //rsDebug("v2", v2);
-        //rsDebug("out", convert_int4(*out));
-    }
-    #endif
+    uchar4 o = convert_uchar4(v2);
+    o.a = 0xff;
+    return o;
 }
 
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/colormatrix.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/colormatrix.rs
similarity index 97%
rename from java/tests/ImageProcessing2/src/com/android/rs/image/colormatrix.fs
rename to java/tests/ImageProcessing2/src/com/android/rs/image/colormatrix.rs
index a1bcaf8..d13ac64 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/colormatrix.fs
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/colormatrix.rs
@@ -15,6 +15,7 @@
  */
 
 #include "ip.rsh"
+#pragma rs_fp_relaxed
 
 static rs_matrix4x4 Mat;
 
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/contrast.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/contrast.rs
index d3743d3..71cb8c6 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/contrast.rs
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/contrast.rs
@@ -15,6 +15,7 @@
  */
 
 #include "ip.rsh"
+#pragma rs_fp_relaxed
 
 static float brightM = 0.f;
 static float brightC = 0.f;
@@ -24,14 +25,10 @@
     brightC = 127.f - brightM * 127.f;
 }
 
-void contrast(const uchar4 *in, uchar4 *out)
-{
-#if 0
-    out->r = rsClamp((int)(brightM * in->r + brightC), 0, 255);
-    out->g = rsClamp((int)(brightM * in->g + brightC), 0, 255);
-    out->b = rsClamp((int)(brightM * in->b + brightC), 0, 255);
-#else
-    float3 v = convert_float3(in->rgb) * brightM + brightC;
-    out->rgb = convert_uchar3(clamp(v, 0.f, 255.f));
-#endif
+uchar4 RS_KERNEL contrast(uchar4 in) {
+    float3 v = convert_float3(in.rgb) * brightM + brightC;
+    uchar4 o;
+    o.rgb = convert_uchar3(clamp(v, 0.f, 255.f));
+    o.a = 0xff;
+    return o;
 }
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/convolve3x3.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/convolve3x3.rs
new file mode 100644
index 0000000..3d811ce
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/convolve3x3.rs
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+#pragma rs_fp_relaxed
+
+int32_t gWidth;
+int32_t gHeight;
+rs_allocation gIn;
+
+float gCoeffs[9];
+
+uchar4 RS_KERNEL root(uint32_t x, uint32_t y) {
+    uint32_t x1 = min((int32_t)x+1, gWidth-1);
+    uint32_t x2 = max((int32_t)x-1, 0);
+    uint32_t y1 = min((int32_t)y+1, gHeight-1);
+    uint32_t y2 = max((int32_t)y-1, 0);
+
+    float4 sum = convert_float4(rsGetElementAt_uchar4(gIn, x1, y1)) * gCoeffs[0];
+    sum += convert_float4(rsGetElementAt_uchar4(gIn, x, y1)) * gCoeffs[1];
+    sum += convert_float4(rsGetElementAt_uchar4(gIn, x2, y1)) * gCoeffs[2];
+    sum += convert_float4(rsGetElementAt_uchar4(gIn, x1, y)) * gCoeffs[3];
+    sum += convert_float4(rsGetElementAt_uchar4(gIn, x, y)) * gCoeffs[4];
+    sum += convert_float4(rsGetElementAt_uchar4(gIn, x2, y)) * gCoeffs[5];
+    sum += convert_float4(rsGetElementAt_uchar4(gIn, x1, y2)) * gCoeffs[6];
+    sum += convert_float4(rsGetElementAt_uchar4(gIn, x, y2)) * gCoeffs[7];
+    sum += convert_float4(rsGetElementAt_uchar4(gIn, x2, y2)) * gCoeffs[8];
+
+    sum = clamp(sum, 0.f, 255.f);
+    return convert_uchar4(sum);
+}
+
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/convolve5x5.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/convolve5x5.fs
deleted file mode 100644
index 3849bd1..0000000
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/convolve5x5.fs
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.
- */
-
-#include "ip.rsh"
-
-int32_t gWidth;
-int32_t gHeight;
-rs_allocation gIn;
-
-float gCoeffs[25];
-
-uchar4 RS_KERNEL root(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);
-    return convert_uchar4(p0);
-}
-
-
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs
new file mode 100644
index 0000000..a9ddde2
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#include "ip.rsh"
+#pragma rs_fp_relaxed
+
+int32_t gWidth;
+int32_t gHeight;
+rs_allocation gIn;
+
+float gCoeffs[25];
+
+uchar4 RS_KERNEL root(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 sum = 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]
+
+               + 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]
+
+               + 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]
+
+               + 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]
+
+               + 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];
+
+    return convert_uchar4(clamp(sum, 0.f, 255.f));
+}
+
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/copy.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/copy.rs
similarity index 96%
rename from java/tests/ImageProcessing2/src/com/android/rs/image/copy.fs
rename to java/tests/ImageProcessing2/src/com/android/rs/image/copy.rs
index f36171e..04c86df 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/copy.fs
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/copy.rs
@@ -15,6 +15,7 @@
  */
 
 #include "ip.rsh"
+#pragma rs_fp_relaxed
 
 uchar4 RS_KERNEL root(uchar4 v_in) {
     return v_in;
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/exposure.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/exposure.rs
index 0f05cb9..cd9e733 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/exposure.rs
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/exposure.rs
@@ -15,6 +15,7 @@
  */
 
 #include "ip.rsh"
+#pragma rs_fp_relaxed
 
 static float bright = 0.f;
 
@@ -22,10 +23,12 @@
     bright = 255.f / (255.f - v);
 }
 
-void exposure(const uchar4 *in, uchar4 *out)
+uchar4 RS_KERNEL exposure(uchar4 in)
 {
-    out->r = rsClamp((int)(bright * in->r), 0, 255);
-    out->g = rsClamp((int)(bright * in->g), 0, 255);
-    out->b = rsClamp((int)(bright * in->b), 0, 255);
+    uchar4 out = 0;
+    out.r = rsClamp((int)(bright * in.r), 0, 255);
+    out.g = rsClamp((int)(bright * in.g), 0, 255);
+    out.b = rsClamp((int)(bright * in.b), 0, 255);
+    return out;
 }
 
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs
similarity index 96%
rename from java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.fs
rename to java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs
index ed69ff4..2a18925 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.fs
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs
@@ -15,6 +15,7 @@
  */
 
 #include "ip.rsh"
+#pragma rs_fp_relaxed
 
 #include "fisheye_approx.rsh"
 
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.rs
similarity index 96%
rename from java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.fs
rename to java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.rs
index f986b5d..31646c4 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.fs
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.rs
@@ -15,6 +15,7 @@
  */
 
 #include "ip.rsh"
+#pragma rs_fp_relaxed
 
 #include "fisheye.rsh"
 
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/grain.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/grain.rs
similarity index 98%
rename from java/tests/ImageProcessing2/src/com/android/rs/image/grain.fs
rename to java/tests/ImageProcessing2/src/com/android/rs/image/grain.rs
index 639bf64..6a88378 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/grain.fs
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/grain.rs
@@ -15,6 +15,7 @@
  */
 
 #include "ip.rsh"
+#pragma rs_fp_relaxed
 
 uchar RS_KERNEL genRand() {
     return (uchar)rsRand(0xff);
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/greyscale.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/greyscale.rs
similarity index 97%
rename from java/tests/ImageProcessing2/src/com/android/rs/image/greyscale.fs
rename to java/tests/ImageProcessing2/src/com/android/rs/image/greyscale.rs
index 65bc252..3ac601d 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/greyscale.fs
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/greyscale.rs
@@ -15,6 +15,7 @@
  */
 
 #include "ip.rsh"
+#pragma rs_fp_relaxed
 
 const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
 
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/ip2_convolve3x3.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/ip2_convolve3x3.rs
deleted file mode 100644
index 3df62f0..0000000
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/ip2_convolve3x3.rs
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.
- */
-
-#include "ip.rsh"
-
-int32_t gWidth;
-int32_t gHeight;
-rs_allocation gIn;
-
-float gCoeffs[9];
-
-uchar4 RS_KERNEL root(uint32_t x, uint32_t y) {
-    uint32_t x1 = min((int32_t)x+1, gWidth-1);
-    uint32_t x2 = max((int32_t)x-1, 0);
-    uint32_t y1 = min((int32_t)y+1, gHeight-1);
-    uint32_t y2 = max((int32_t)y-1, 0);
-
-    float4 p00 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y1));
-    float4 p01 = convert_float4(rsGetElementAt_uchar4(gIn, x, y1));
-    float4 p02 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y1));
-    float4 p10 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y));
-    float4 p11 = convert_float4(rsGetElementAt_uchar4(gIn, x, y));
-    float4 p12 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y));
-    float4 p20 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y2));
-    float4 p21 = convert_float4(rsGetElementAt_uchar4(gIn, x, y2));
-    float4 p22 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y2));
-    p00 *= gCoeffs[0];
-    p01 *= gCoeffs[1];
-    p02 *= gCoeffs[2];
-    p10 *= gCoeffs[3];
-    p11 *= gCoeffs[4];
-    p12 *= gCoeffs[5];
-    p20 *= gCoeffs[6];
-    p21 *= gCoeffs[7];
-    p22 *= gCoeffs[8];
-
-    p00 += p01;
-    p02 += p10;
-    p11 += p12;
-    p20 += p21;
-
-    p22 += p00;
-    p02 += p11;
-
-    p20 += p22;
-    p20 += p02;
-
-    p20 = clamp(p20, 0.f, 255.f);
-    return convert_uchar4(p20);
-}
-
-
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/levels.rsh b/java/tests/ImageProcessing2/src/com/android/rs/image/levels.rsh
index e289906..b864493 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/levels.rsh
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/levels.rsh
@@ -21,7 +21,7 @@
 float overInWMinInB;
 rs_matrix3x3 colorMat;
 
-uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
+uchar4 __attribute__((kernel)) root(uchar4 in) {
     uchar4 out;
     float3 pixel = convert_float4(in).rgb;
     pixel = rsMatrixMultiply(&colorMat, pixel);
@@ -34,7 +34,7 @@
     return out;
 }
 
-uchar4 __attribute__((kernel)) root4(uchar4 in, uint32_t x, uint32_t y) {
+uchar4 __attribute__((kernel)) root4(uchar4 in) {
     float4 pixel = convert_float4(in);
     pixel.rgb = rsMatrixMultiply(&colorMat, pixel.rgb);
     pixel = clamp(pixel, 0.f, 255.f);
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs
similarity index 96%
rename from java/tests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.fs
rename to java/tests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs
index 28596ba..c0bc4b7 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.fs
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs
@@ -15,6 +15,7 @@
  */
 
 #include "ip.rsh"
+#pragma rs_fp_relaxed
 
 #include "levels.rsh"
 
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs
index bdbcfcd..99451f0 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs
@@ -53,3 +53,36 @@
                       (0xff * ((iter - (mi3 * 2)) / mi3)), 0xff};
   }
 }
+
+uchar4 RS_KERNEL rootD(uint32_t x, uint32_t y) {
+  double2 p;
+  p.x = lowerBoundX + ((float)x / gDimX) * scaleFactor;
+  p.y = lowerBoundY + ((float)y / gDimY) * scaleFactor;
+
+  double2 t = 0;
+  double2 t2 = t * t;
+  int iter = 0;
+  while((t2.x + t2.y < 4.f) && (iter < gMaxIteration)) {
+    double 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
+    return (uchar4){0, 0, 0, 0xff};
+  } else {
+    double mi3 = gMaxIteration / 3.f;
+    if (iter <= (gMaxIteration / 3))
+      return (uchar4){0xff * (iter / mi3), 0, 0, 0xff};
+    else if (iter <= (((gMaxIteration / 3) * 2)))
+      return (uchar4){0xff - (0xff * ((iter - mi3) / mi3)),
+                      (0xff * ((iter - mi3) / mi3)), 0, 0xff};
+    else
+      return (uchar4){0, 0xff - (0xff * ((iter - (mi3 * 2)) / mi3)),
+                      (0xff * ((iter - (mi3 * 2)) / mi3)), 0xff};
+  }
+}
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/posterize.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/posterize.rs
new file mode 100644
index 0000000..043ea5e
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/posterize.rs
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ip.rsh"
+#pragma rs_fp_relaxed
+
+rs_allocation inputImage;
+
+float intensityLow = 0.f;
+float intensityHigh;
+uchar4 color;
+const static float3 mono = {0.299f, 0.587f, 0.114f};
+
+void setParams(float intensHigh, float intensLow, uchar r, uchar g, uchar b) {
+    intensityLow = intensLow;
+    intensityHigh = intensHigh;
+    uchar4 hats = {r, g, b, 255};
+    color = hats;
+}
+
+uchar4 RS_KERNEL root(uchar4 v_in, uint32_t x, uint32_t y) {
+    uchar4 refpix = rsGetElementAt_uchar4(inputImage, x, y);
+    float pixelIntensity = dot(rsUnpackColor8888(refpix).rgb, mono);
+    if ((pixelIntensity <= intensityHigh) && (pixelIntensity >= intensityLow)) {
+        return color;
+    } else {
+        return v_in;
+    }
+}
+
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/resize.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/resize.rs
new file mode 100644
index 0000000..ec283be
--- /dev/null
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/resize.rs
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ip.rsh"
+#pragma rs_fp_relaxed
+
+int32_t gWidthIn;
+int32_t gHeightIn;
+rs_allocation gIn;
+float scale;
+
+
+uchar4 __attribute__((kernel)) nearest(uint32_t x, uint32_t y) {
+    float xf = clamp(x * scale, 0.f, (float)gWidthIn - 1.f);
+    float yf = clamp(y * scale, 0.f, (float)gHeightIn - 1.f);
+    uint32_t ix = xf;
+    uint32_t iy = yf;
+
+    uchar4 tmp = rsGetElementAt_uchar4(gIn, ix, iy);
+    tmp.a = 0xff;
+    return tmp;
+}
+
+
+static float4 cubicInterpolate (float4 p0,float4 p1,float4 p2,float4 p3 , float x) {
+    return p1 + 0.5f * x * (p2 - p0 + x * (2.f * p0 - 5.f * p1 + 4.f * p2 - p3
+            + x * (3.f * (p1 - p2) + p3 - p0)));
+}
+
+uchar4 __attribute__((kernel)) bicubic(uint32_t x, uint32_t y) {
+    float xf = x * scale;
+    float yf = y * scale;
+
+    int startx = (int) floor(xf - 2);
+    int starty = (int) floor(yf - 2);
+    xf = xf - floor(xf);
+    yf = yf - floor(yf);
+    int maxx = gWidthIn - 1;
+    int maxy = gHeightIn - 1;
+
+    uint32_t xs0 = (uint32_t) max(0, startx + 0);
+    uint32_t xs1 = (uint32_t) max(0, startx + 1);
+    uint32_t xs2 = (uint32_t) min(maxx, startx + 2);
+    uint32_t xs3 = (uint32_t) min(maxx, startx + 3);
+
+    uint32_t ys0 = (uint32_t) max(0, starty + 0);
+    uint32_t ys1 = (uint32_t) max(0, starty + 1);
+    uint32_t ys2 = (uint32_t) min(maxy, starty + 2);
+    uint32_t ys3 = (uint32_t) min(maxy, starty + 3);
+
+    float4 p00 = convert_float4(rsGetElementAt_uchar4(gIn, xs0, ys0));
+    float4 p01 = convert_float4(rsGetElementAt_uchar4(gIn, xs1, ys0));
+    float4 p02 = convert_float4(rsGetElementAt_uchar4(gIn, xs2, ys0));
+    float4 p03 = convert_float4(rsGetElementAt_uchar4(gIn, xs3, ys0));
+    float4 p0  = cubicInterpolate(p00, p01, p02, p03, xf);
+
+    float4 p10 = convert_float4(rsGetElementAt_uchar4(gIn, xs0, ys1));
+    float4 p11 = convert_float4(rsGetElementAt_uchar4(gIn, xs1, ys1));
+    float4 p12 = convert_float4(rsGetElementAt_uchar4(gIn, xs2, ys1));
+    float4 p13 = convert_float4(rsGetElementAt_uchar4(gIn, xs3, ys1));
+    float4 p1  = cubicInterpolate(p10, p11, p12, p13, xf);
+
+    float4 p20 = convert_float4(rsGetElementAt_uchar4(gIn, xs0, ys2));
+    float4 p21 = convert_float4(rsGetElementAt_uchar4(gIn, xs1, ys2));
+    float4 p22 = convert_float4(rsGetElementAt_uchar4(gIn, xs2, ys2));
+    float4 p23 = convert_float4(rsGetElementAt_uchar4(gIn, xs3, ys2));
+    float4 p2  = cubicInterpolate(p20, p21, p22, p23, xf);
+
+    float4 p30 = convert_float4(rsGetElementAt_uchar4(gIn, xs0, ys3));
+    float4 p31 = convert_float4(rsGetElementAt_uchar4(gIn, xs1, ys3));
+    float4 p32 = convert_float4(rsGetElementAt_uchar4(gIn, xs2, ys3));
+    float4 p33 = convert_float4(rsGetElementAt_uchar4(gIn, xs3, ys3));
+    float4 p3  = cubicInterpolate(p30, p31, p32, p33, xf);
+
+    float4 p  = cubicInterpolate(p0, p1, p2, p3, yf);
+    p = clamp(p, 0.f, 255.f);
+    return convert_uchar4(p);
+}
+
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/shadows.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/shadows.rs
index f6c149d..f852aae 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/shadows.rs
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/shadows.rs
@@ -15,20 +15,20 @@
  */
 
 #include "ip.rsh"
-//#pragma rs_fp_relaxed
+#pragma rs_fp_relaxed
 
-static double shadowFilterMap[] = {
-    -0.00591,  0.0001,
-     1.16488,  0.01668,
-    -0.18027, -0.06791,
-    -0.12625,  0.09001,
-     0.15065, -0.03897
+static float shadowFilterMap[] = {
+    -0.00591f,  0.0001f,
+     1.16488f,  0.01668f,
+    -0.18027f, -0.06791f,
+    -0.12625f,  0.09001f,
+     0.15065f, -0.03897f
 };
 
-static double poly[] = {
-    0., 0.,
-    0., 0.,
-    0.
+static float poly[] = {
+    0.f, 0.f,
+    0.f, 0.f,
+    0.f
 };
 
 static const int ABITS = 4;
@@ -36,10 +36,10 @@
 static const int k1=255 << ABITS;
 static const int k2=HSCALE << ABITS;
 
-static double fastevalPoly(double *poly,int n, double x){
+static float fastevalPoly(float *poly,int n, float x){
 
-    double f =x;
-    double sum = poly[0]+poly[1]*f;
+    float f =x;
+    float sum = poly[0]+poly[1]*f;
     int i;
     for (i = 2; i < n; i++) {
         f*=x;
@@ -177,16 +177,15 @@
 }
 
 void prepareShadows(float scale) {
-    double s = (scale>=0)?scale:scale/5;
+    float s = (scale>=0) ? scale : scale / 5.f;
     for (int i = 0; i < 5; i++) {
         poly[i] = fastevalPoly(shadowFilterMap+i*2,2 , s);
     }
 }
 
-void shadowsKernel(const uchar4 *in, uchar4 *out) {
-    ushort3 hsv = rgb2hsv(*in);
-    double v = (fastevalPoly(poly,5,hsv.x/4080.)*4080);
-    if (v>4080) v = 4080;
-    hsv.x = (unsigned short) ((v>0)?v:0);
-    *out = hsv2rgb(hsv);
+uchar4 RS_KERNEL shadowsKernel(uchar4 in) {
+    ushort3 hsv = rgb2hsv(in);
+    float v = (fastevalPoly(poly, 5, hsv.x * (1.f / 4080.f)) * 4080.f);
+    hsv.x = (unsigned short) clamp(v, 0.f, 4080.f);
+    return hsv2rgb(hsv);
 }
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/threshold.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/threshold.rs
similarity index 98%
rename from java/tests/ImageProcessing2/src/com/android/rs/image/threshold.fs
rename to java/tests/ImageProcessing2/src/com/android/rs/image/threshold.rs
index 96996f5..40d4fa2 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/threshold.fs
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/threshold.rs
@@ -15,7 +15,7 @@
  */
 
 #include "ip.rsh"
-
+#pragma rs_fp_relaxed
 
 int height;
 int width;
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/copy.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/util.rs
similarity index 84%
copy from java/tests/ImageProcessing2/src/com/android/rs/image/copy.fs
copy to java/tests/ImageProcessing2/src/com/android/rs/image/util.rs
index f36171e..f11b06c 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/copy.fs
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/util.rs
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2014 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,8 +16,7 @@
 
 #include "ip.rsh"
 
-uchar4 RS_KERNEL root(uchar4 v_in) {
-    return v_in;
+void utilSendMessage(int op) {
+    rsSendToClient(op);
 }
 
-
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/vibrance.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/vibrance.rs
index ad4de58..865c77e 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/vibrance.rs
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/vibrance.rs
@@ -15,6 +15,7 @@
  */
 
 #include "ip.rsh"
+#pragma rs_fp_relaxed
 
 float vibrance = 0.f;
 
@@ -22,49 +23,36 @@
 static const float Gf = 0.587f;
 static const float Bf = 0.114f;
 
-static float S  = 0.f;
-static float MS = 0.f;
-static float Rt = 0.f;
-static float Gt = 0.f;
-static float Bt = 0.f;
 static float Vib = 0.f;
 
-void vibranceKernel(const uchar4 *in, uchar4 *out) {
+uchar4 RS_KERNEL vibranceKernel(uchar4 in) {
+    int r = in.r;
+    int g = in.g;
+    int b = in.b;
+    float red = (r-max(g, b)) * (1.f / 256.f);
+    float S = (float)(Vib/(1+native_exp(-red*3)))+1;
+    float MS = 1.0f - S;
+    float Rt = Rf * MS;
+    float Gt = Gf * MS;
+    float Bt = Bf * MS;
+    int t = (r + g) >> 1;
 
-    float R, G, B;
-
-    int r = in->r;
-    int g = in->g;
-    int b = in->b;
-    float red = (r-max(g, b))/256.f;
-    float sx = (float)(Vib/(1+native_exp(-red*3)));
-    S = sx+1;
-    MS = 1.0f - S;
-    Rt = Rf * MS;
-    Gt = Gf * MS;
-    Bt = Bf * MS;
-    int t = (r + g) / 2;
-    R = r;
-    G = g;
-    B = b;
+    float R = r;
+    float G = g;
+    float B = b;
 
     float Rc = R * (Rt + S) + G * Gt + B * Bt;
     float Gc = R * Rt + G * (Gt + S) + B * Bt;
     float Bc = R * Rt + G * Gt + B * (Bt + S);
 
-    out->r = rsClamp(Rc, 0, 255);
-    out->g = rsClamp(Gc, 0, 255);
-    out->b = rsClamp(Bc, 0, 255);
-
+    uchar4 o;
+    o.r = rsClamp(Rc, 0, 255);
+    o.g = rsClamp(Gc, 0, 255);
+    o.b = rsClamp(Bc, 0, 255);
+    o.a = 0xff;
+    return o;
 }
 
 void prepareVibrance() {
-
     Vib = vibrance/100.f;
-    S  = Vib + 1;
-    MS = 1.0f - S;
-    Rt = Rf * MS;
-    Gt = Gf * MS;
-    Bt = Bf * MS;
-
 }
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs
similarity index 96%
rename from java/tests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.fs
rename to java/tests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs
index 00cbbc4..347eb7a 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.fs
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs
@@ -15,6 +15,7 @@
  */
 
 #include "ip.rsh"
+#pragma rs_fp_relaxed
 
 #include "vignette_approx.rsh"
 
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.fs b/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.rs
similarity index 96%
rename from java/tests/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.fs
rename to java/tests/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.rs
index 8202c5c..262d516 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.fs
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.rs
@@ -15,6 +15,7 @@
  */
 
 #include "ip.rsh"
+#pragma rs_fp_relaxed
 
 #include "vignette.rsh"
 
diff --git a/java/tests/ImageProcessing2/src/com/android/rs/image/wbalance.rs b/java/tests/ImageProcessing2/src/com/android/rs/image/wbalance.rs
index 6650671..58f64d1 100644
--- a/java/tests/ImageProcessing2/src/com/android/rs/image/wbalance.rs
+++ b/java/tests/ImageProcessing2/src/com/android/rs/image/wbalance.rs
@@ -15,7 +15,7 @@
  */
 
 #include "ip.rsh"
-//#pragma rs_fp_relaxed
+#pragma rs_fp_relaxed
 
 static int histR[256] = {0}, histG[256] = {0}, histB[256] = {0};
 
@@ -23,9 +23,7 @@
 uint32_t histogramHeight;
 uint32_t histogramWidth;
 
-static float scaleR;
-static float scaleG;
-static float scaleB;
+static float3 scale;
 
 static uchar4 estimateWhite() {
 
@@ -115,28 +113,19 @@
     int maximum = max(estimation.r, max(estimation.g, estimation.b));
     float avg = (minimum + maximum) / 2.f;
 
-    scaleR =  avg/estimation.r;
-    scaleG =  avg/estimation.g;
-    scaleB =  avg/estimation.b;
-
+    scale.r =  avg/estimation.r;
+    scale.g =  avg/estimation.g;
+    scale.b =  avg/estimation.b;
 }
 
-static unsigned char contrastClamp(int c)
-{
-    int N = 255;
-    c &= ~(c >> 31);
-    c -= N;
-    c &= (c >> 31);
-    c += N;
-    return  (unsigned char) c;
+uchar4 RS_KERNEL whiteBalanceKernel(uchar4 in) {
+    float3 t = convert_float3(in.rgb);
+    t *= scale;
+    t = min(t, 255.f);
+
+    uchar4 out;
+    out.rgb = convert_uchar3(t);
+    out.a = 255;
+    return out;
 }
 
-void whiteBalanceKernel(const uchar4 *in, uchar4 *out) {
-    float Rc =  in->r*scaleR;
-    float Gc =  in->g*scaleG;
-    float Bc =  in->b*scaleB;
-
-    out->r = contrastClamp(Rc);
-    out->g = contrastClamp(Gc);
-    out->b = contrastClamp(Bc);
-}
diff --git a/java/tests/ImageProcessing_jb/src/com/android/rs/image/TestBase.java b/java/tests/ImageProcessing_jb/src/com/android/rs/image/TestBase.java
index 3de9809..589f009 100644
--- a/java/tests/ImageProcessing_jb/src/com/android/rs/image/TestBase.java
+++ b/java/tests/ImageProcessing_jb/src/com/android/rs/image/TestBase.java
@@ -44,7 +44,7 @@
     protected RenderScript mRS;
     protected Allocation mInPixelsAllocation;
     protected Allocation mInPixelsAllocation2;
-    protected Allocation mOutPixelsAllocation;
+    public Allocation mOutPixelsAllocation;
     protected ImageProcessingActivityJB act;
 
     private class MessageProcessor extends RenderScript.RSMessageHandler {
diff --git a/update_rs_prebuilts.sh b/update_rs_prebuilts.sh
index 2f0163b..362a0c0 100755
--- a/update_rs_prebuilts.sh
+++ b/update_rs_prebuilts.sh
@@ -45,6 +45,9 @@
 # HOST_LIB_DIR allows us to pick up the built librsrt_*.bc libraries.
 HOST_LIB_DIR=$ANDROID_HOST_OUT/lib
 
+# HOST_LIB64_DIR
+HOST_LIB64_DIR=$ANDROID_HOST_OUT/lib64
+
 # PREBUILTS_DIR is where we want to copy our new files to.
 PREBUILTS_DIR=$MY_ANDROID_DIR/prebuilts/sdk/
 
@@ -130,7 +133,7 @@
 
     for a in `find renderscript/lib/$t -name \*.bc`; do
       file=`basename $a`
-      cp `find $HOST_LIB_DIR $sys_lib_dir $obj_lib_dir -name $file | head -1` $a || exit 5
+      cp `find $HOST_LIB_DIR $HOST_LIB64_DIR $sys_lib_dir $obj_lib_dir -name $file | head -1` $a || exit 5
     done
   done