More flexible structure for rs benchmark.

Major refactoring to allow adding more benchmarks easily.

Change-Id: I00e7c900b7383498da28cb9ffdc6fff855c5a581
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/FillTest.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/FillTest.java
new file mode 100644
index 0000000..06b4af7
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/FillTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.perftest;
+
+import android.os.Environment;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+
+import android.util.Log;
+
+
+public class FillTest implements RsBenchBaseTest{
+
+    private static final String TAG = "FillTest";
+    private RenderScriptGL mRS;
+    private Resources mRes;
+
+    // Custom shaders
+    private ProgramFragment mProgFragmentMultitex;
+    private ProgramFragment mProgFragmentSingletex;
+    private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
+    int mBenchmarkDimX;
+    int mBenchmarkDimY;
+
+    private ScriptC_fill_test mFillScript;
+    ScriptField_TestScripts_s.Item[] mTests;
+
+    private final String[] mNames = {
+        "Fill screen 10x singletexture",
+        "Fill screen 10x 3tex multitexture",
+        "Fill screen 10x blended singletexture",
+        "Fill screen 10x blended 3tex multitexture"
+    };
+
+    public FillTest() {
+        mOptionsARGB.inScaled = false;
+        mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
+        mBenchmarkDimX = 1280;
+        mBenchmarkDimY = 720;
+    }
+
+    void addTest(int index, int testId, int blend, int quadCount) {
+        mTests[index] = new ScriptField_TestScripts_s.Item();
+        mTests[index].testScript = mFillScript;
+        mTests[index].testName = Allocation.createFromString(mRS,
+                                                             mNames[index],
+                                                             Allocation.USAGE_SCRIPT);
+
+        ScriptField_FillTestData_s.Item dataItem = new ScriptField_FillTestData_s.Item();
+        dataItem.testId = testId;
+        dataItem.blend = blend;
+        dataItem.quadCount = quadCount;
+        ScriptField_FillTestData_s testData = new ScriptField_FillTestData_s(mRS, 1);
+        testData.set(dataItem, 0, true);
+        mTests[index].testData = testData.getAllocation();
+    }
+
+    public boolean init(RenderScriptGL rs, Resources res) {
+        mRS = rs;
+        mRes = res;
+        initCustomShaders();
+        initFillScript();
+        mTests = new ScriptField_TestScripts_s.Item[mNames.length];
+
+        int index = 0;
+
+        addTest(index++, 1 /*testId*/, 0 /*blend*/, 10 /*quadCount*/);
+        addTest(index++, 0 /*testId*/, 0 /*blend*/, 10 /*quadCount*/);
+        addTest(index++, 1 /*testId*/, 1 /*blend*/, 10 /*quadCount*/);
+        addTest(index++, 0 /*testId*/, 1 /*blend*/, 10 /*quadCount*/);
+
+        return true;
+    }
+
+    public ScriptField_TestScripts_s.Item[] getTests() {
+        return mTests;
+    }
+
+    public String[] getTestNames() {
+        return mNames;
+    }
+
+    private void initCustomShaders() {
+        ProgramFragment.Builder pfbCustom = new ProgramFragment.Builder(mRS);
+        pfbCustom.setShader(mRes, R.raw.multitexf);
+        for (int texCount = 0; texCount < 3; texCount ++) {
+            pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
+        }
+        mProgFragmentMultitex = pfbCustom.create();
+
+        pfbCustom = new ProgramFragment.Builder(mRS);
+        pfbCustom.setShader(mRes, R.raw.singletexf);
+        pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
+        mProgFragmentSingletex = pfbCustom.create();
+    }
+
+    private Allocation loadTextureARGB(int id) {
+        Bitmap b = BitmapFactory.decodeResource(mRes, id, mOptionsARGB);
+        return Allocation.createFromBitmap(mRS, b,
+                Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
+                Allocation.USAGE_GRAPHICS_TEXTURE);
+    }
+
+    private Allocation loadTextureRGB(int id) {
+        return Allocation.createFromBitmapResource(mRS, mRes, id,
+                Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
+                Allocation.USAGE_GRAPHICS_TEXTURE);
+    }
+
+    void initFillScript() {
+        mFillScript = new ScriptC_fill_test(mRS, mRes, R.raw.fill_test);
+
+        ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
+        ProgramVertexFixedFunction progVertex = pvb.create();
+        ProgramVertexFixedFunction.Constants PVA = new ProgramVertexFixedFunction.Constants(mRS);
+        ((ProgramVertexFixedFunction)progVertex).bindConstants(PVA);
+        Matrix4f proj = new Matrix4f();
+        proj.loadOrthoWindow(mBenchmarkDimX, mBenchmarkDimY);
+        PVA.setProjection(proj);
+        mFillScript.set_gProgVertex(progVertex);
+
+        mFillScript.set_gProgFragmentTexture(mProgFragmentSingletex);
+        mFillScript.set_gProgFragmentMultitex(mProgFragmentMultitex);
+        mFillScript.set_gProgStoreBlendNone(ProgramStore.BLEND_NONE_DEPTH_NONE(mRS));
+        mFillScript.set_gProgStoreBlendAlpha(ProgramStore.BLEND_ALPHA_DEPTH_NONE(mRS));
+
+        mFillScript.set_gLinearClamp(Sampler.CLAMP_LINEAR(mRS));
+        mFillScript.set_gLinearWrap(Sampler.WRAP_LINEAR(mRS));
+        mFillScript.set_gTexTorus(loadTextureRGB(R.drawable.torusmap));
+        mFillScript.set_gTexOpaque(loadTextureRGB(R.drawable.data));
+        mFillScript.set_gTexTransparent(loadTextureARGB(R.drawable.leaf));
+        mFillScript.set_gTexChecker(loadTextureRGB(R.drawable.checker));
+    }
+}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/MeshTest.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/MeshTest.java
new file mode 100644
index 0000000..f39e7db
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/MeshTest.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.perftest;
+
+import android.os.Environment;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.renderscript.*;
+import android.renderscript.Element.DataKind;
+import android.renderscript.Element.DataType;
+import android.renderscript.Allocation.MipmapControl;
+import android.renderscript.Program.TextureType;
+import android.renderscript.RenderScript.RSMessageHandler;
+import android.renderscript.Mesh.Primitive;
+import android.renderscript.Matrix4f;
+import android.renderscript.ProgramVertexFixedFunction;
+
+import android.util.Log;
+
+
+public class MeshTest implements RsBenchBaseTest{
+
+    private static final String TAG = "MeshTest";
+    private RenderScriptGL mRS;
+    private Resources mRes;
+
+    int mBenchmarkDimX;
+    int mBenchmarkDimY;
+
+    private Mesh m10by10Mesh;
+    private Mesh m100by100Mesh;
+    private Mesh mWbyHMesh;
+
+    private ScriptC_mesh_test mGeoScript;
+
+    private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
+
+    ScriptField_TestScripts_s.Item[] mTests;
+
+    private final String[] mNames = {
+        "Full screen mesh 10 by 10",
+        "Full screen mesh 100 by 100",
+        "Full screen mesh W / 4 by H / 4"
+    };
+
+    public MeshTest() {
+        mBenchmarkDimX = 1280;
+        mBenchmarkDimY = 720;
+    }
+
+    void addTest(int index, int meshNum) {
+        mTests[index] = new ScriptField_TestScripts_s.Item();
+        mTests[index].testScript = mGeoScript;
+        mTests[index].testName = Allocation.createFromString(mRS,
+                                                             mNames[index],
+                                                             Allocation.USAGE_SCRIPT);
+
+        ScriptField_MeshTestData_s.Item dataItem = new ScriptField_MeshTestData_s.Item();
+        dataItem.meshNum = meshNum;
+        ScriptField_MeshTestData_s testData = new ScriptField_MeshTestData_s(mRS, 1);
+        testData.set(dataItem, 0, true);
+        mTests[index].testData = testData.getAllocation();
+    }
+
+    public boolean init(RenderScriptGL rs, Resources res) {
+        mRS = rs;
+        mRes = res;
+        initGeoScript();
+        mTests = new ScriptField_TestScripts_s.Item[mNames.length];
+
+        int index = 0;
+        addTest(index++, 0 /*meshNum*/);
+        addTest(index++, 1 /*meshNum*/);
+        addTest(index++, 2 /*meshNum*/);
+
+        return true;
+    }
+
+    public ScriptField_TestScripts_s.Item[] getTests() {
+        return mTests;
+    }
+
+    public String[] getTestNames() {
+        return mNames;
+    }
+
+    private Mesh getMbyNMesh(float width, float height, int wResolution, int hResolution) {
+
+        Mesh.TriangleMeshBuilder tmb = new Mesh.TriangleMeshBuilder(mRS,
+                                           2, Mesh.TriangleMeshBuilder.TEXTURE_0);
+
+        for (int y = 0; y <= hResolution; y++) {
+            final float normalizedY = (float)y / hResolution;
+            final float yOffset = (normalizedY - 0.5f) * height;
+            for (int x = 0; x <= wResolution; x++) {
+                float normalizedX = (float)x / wResolution;
+                float xOffset = (normalizedX - 0.5f) * width;
+                tmb.setTexture((float)x % 2, (float)y % 2);
+                tmb.addVertex(xOffset, yOffset);
+             }
+        }
+
+        for (int y = 0; y < hResolution; y++) {
+            final int curY = y * (wResolution + 1);
+            final int belowY = (y + 1) * (wResolution + 1);
+            for (int x = 0; x < wResolution; x++) {
+                int curV = curY + x;
+                int belowV = belowY + x;
+                tmb.addTriangle(curV, belowV, curV + 1);
+                tmb.addTriangle(belowV, belowV + 1, curV + 1);
+            }
+        }
+
+        return tmb.create(true);
+    }
+
+    private Allocation loadTextureRGB(int id) {
+        return Allocation.createFromBitmapResource(mRS, mRes, id,
+                Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
+                Allocation.USAGE_GRAPHICS_TEXTURE);
+    }
+
+    void initGeoScript() {
+        mGeoScript = new ScriptC_mesh_test(mRS, mRes, R.raw.mesh_test);
+
+        ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
+        ProgramVertexFixedFunction progVertex = pvb.create();
+        ProgramVertexFixedFunction.Constants PVA = new ProgramVertexFixedFunction.Constants(mRS);
+        ((ProgramVertexFixedFunction)progVertex).bindConstants(PVA);
+        Matrix4f proj = new Matrix4f();
+        proj.loadOrthoWindow(mBenchmarkDimX, mBenchmarkDimY);
+        PVA.setProjection(proj);
+
+        mGeoScript.set_gProgVertex(progVertex);
+        ProgramFragmentFixedFunction.Builder texBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
+        texBuilder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
+                              ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
+        mGeoScript.set_gProgFragmentTexture(texBuilder.create());
+        mGeoScript.set_gProgStoreBlendNone(ProgramStore.BLEND_NONE_DEPTH_NONE(mRS));
+
+        mGeoScript.set_gLinearClamp(Sampler.CLAMP_LINEAR(mRS));
+        mGeoScript.set_gTexOpaque(loadTextureRGB(R.drawable.data));
+
+        m10by10Mesh = getMbyNMesh(mBenchmarkDimX, mBenchmarkDimY, 10, 10);
+        m100by100Mesh = getMbyNMesh(mBenchmarkDimX, mBenchmarkDimY, 100, 100);
+        mWbyHMesh= getMbyNMesh(mBenchmarkDimX, mBenchmarkDimY, mBenchmarkDimX/4, mBenchmarkDimY/4);
+
+        mGeoScript.set_g10by10Mesh(m10by10Mesh);
+        mGeoScript.set_g100by100Mesh(m100by100Mesh);
+        mGeoScript.set_gWbyHMesh(mWbyHMesh);
+    }
+}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchBaseTest.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchBaseTest.java
new file mode 100644
index 0000000..a9e1777
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchBaseTest.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.perftest;
+import android.renderscript.*;
+import android.content.res.Resources;
+
+interface RsBenchBaseTest {
+    boolean init(RenderScriptGL rs, Resources res);
+
+    ScriptField_TestScripts_s.Item[] getTests();
+    String[] getTestNames();
+}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java
index c375be5..b8360d7 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2010-2011 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -26,16 +26,11 @@
 
 import android.os.Environment;
 import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
 import android.renderscript.*;
 import android.renderscript.Element.DataKind;
 import android.renderscript.Element.DataType;
 import android.renderscript.Allocation.MipmapControl;
 import android.renderscript.Program.TextureType;
-import android.renderscript.ProgramStore.DepthFunc;
-import android.renderscript.ProgramStore.BlendSrcFunc;
-import android.renderscript.ProgramStore.BlendDstFunc;
 import android.renderscript.RenderScript.RSMessageHandler;
 import android.renderscript.Sampler.Value;
 import android.renderscript.Mesh.Primitive;
@@ -48,10 +43,6 @@
 public class RsBenchRS {
 
     private static final String TAG = "RsBenchRS";
-    private static final String SAMPLE_TEXT = "Bench Test";
-    private static final String LIST_TEXT =
-      "This is a sample list of text to show in the list view";
-    private static int PARTICLES_COUNT = 12000;
     int mWidth;
     int mHeight;
     int mLoops;
@@ -68,8 +59,6 @@
         mRes = res;
         mWidth = width;
         mHeight = height;
-        mOptionsARGB.inScaled = false;
-        mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
         mMode = 0;
         mMaxModes = 0;
         mLoops = loops;
@@ -84,10 +73,8 @@
     private Resources mRes;
     private RenderScriptGL mRS;
 
-    private ProgramStore mProgStoreBlendNoneDepth;
     private ProgramStore mProgStoreBlendNone;
     private ProgramStore mProgStoreBlendAlpha;
-    private ProgramStore mProgStoreBlendAdd;
 
     private ProgramFragment mProgFragmentTexture;
     private ProgramFragment mProgFragmentColor;
@@ -96,47 +83,9 @@
     private ProgramVertexFixedFunction.Constants mPVA;
     private ProgramVertexFixedFunction.Constants mPvProjectionAlloc;
 
-    // Custom shaders
-    private ProgramVertex mProgVertexCustom;
-    private ProgramFragment mProgFragmentCustom;
-    private ProgramFragment mProgFragmentMultitex;
-    private ProgramVertex mProgVertexPixelLight;
-    private ProgramVertex mProgVertexPixelLightMove;
-    private ProgramFragment mProgFragmentPixelLight;
-    private ScriptField_VertexShaderConstants_s mVSConst;
-    private ScriptField_FragentShaderConstants_s mFSConst;
-    private ScriptField_VertexShaderConstants3_s mVSConstPixel;
-    private ScriptField_FragentShaderConstants3_s mFSConstPixel;
-
-
-    private Allocation mTexTorus;
-    private Allocation mTexOpaque;
-    private Allocation mTexTransparent;
-    private Allocation mTexChecker;
-    private Allocation mTexGlobe;
-
-    private Mesh m10by10Mesh;
-    private Mesh m100by100Mesh;
-    private Mesh mWbyHMesh;
-    private Mesh mTorus;
-    private Mesh mSingleMesh;
-    private Mesh mParticlesMesh;
-
-    Font mFontSans;
-    Font mFontSerif;
-    private Allocation mTextAlloc;
-
-    private ScriptField_ListAllocs_s mTextureAllocs;
-    private ScriptField_ListAllocs_s mSampleTextAllocs;
-    private ScriptField_ListAllocs_s mSampleListViewAllocs;
-    private ScriptField_VpConsts mPvStarAlloc;
-
-
     private ScriptC_rsbench mScript;
-    private ScriptC_text_test mTextScript;
-    private ScriptC_torus_test mTorusScript;
 
-    private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
+    ScriptField_TestScripts_s.Item[] mIndividualTests;
 
     int mMode;
     int mMaxModes;
@@ -144,10 +93,39 @@
     String[] mTestNames;
     float[] mLocalTestResults;
 
-    public void onActionDown(int x, int y) {
-        mMode ++;
-        mMode = mMode % mMaxModes;
-        mScript.set_gDisplayMode(mMode);
+    void appendTests(RsBenchBaseTest testSet) {
+        ScriptField_TestScripts_s.Item[] newTests = testSet.getTests();
+        if (mIndividualTests != null) {
+            ScriptField_TestScripts_s.Item[] combined;
+            combined = new ScriptField_TestScripts_s.Item[newTests.length + mIndividualTests.length];
+            System.arraycopy(mIndividualTests, 0, combined, 0, mIndividualTests.length);
+            System.arraycopy(newTests, 0, combined, mIndividualTests.length, newTests.length);
+            mIndividualTests = combined;
+        } else {
+            mIndividualTests = newTests;
+        }
+
+        String[] newNames = testSet.getTestNames();
+        if (mTestNames != null) {
+            String[] combinedNames;
+            combinedNames = new String[newNames.length + mTestNames.length];
+            System.arraycopy(mTestNames, 0, combinedNames, 0, mTestNames.length);
+            System.arraycopy(newNames, 0, combinedNames, mTestNames.length, newNames.length);
+            mTestNames = combinedNames;
+        } else {
+            mTestNames = newNames;
+        }
+    }
+
+    void createTestAllocation() {
+        int numTests = mIndividualTests.length;
+        ScriptField_TestScripts_s allTests;
+        allTests = new ScriptField_TestScripts_s(mRS, numTests);
+        for (int i = 0; i < numTests; i ++) {
+            allTests.set(mIndividualTests[i], i, false);
+        }
+        allTests.copyAll();
+        mScript.bind_gTestScripts(allTests);
     }
 
     private void saveTestResults() {
@@ -225,98 +203,6 @@
         }
     }
 
-    ProgramStore BLEND_ADD_DEPTH_NONE(RenderScript rs) {
-        ProgramStore.Builder builder = new ProgramStore.Builder(rs);
-        builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
-        builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
-        builder.setDitherEnabled(false);
-        builder.setDepthMaskEnabled(false);
-        return builder.create();
-    }
-
-    private Mesh getMbyNMesh(float width, float height, int wResolution, int hResolution) {
-
-        Mesh.TriangleMeshBuilder tmb = new Mesh.TriangleMeshBuilder(mRS,
-                                           2, Mesh.TriangleMeshBuilder.TEXTURE_0);
-
-        for (int y = 0; y <= hResolution; y++) {
-            final float normalizedY = (float)y / hResolution;
-            final float yOffset = (normalizedY - 0.5f) * height;
-            for (int x = 0; x <= wResolution; x++) {
-                float normalizedX = (float)x / wResolution;
-                float xOffset = (normalizedX - 0.5f) * width;
-                tmb.setTexture((float)x % 2, (float)y % 2);
-                tmb.addVertex(xOffset, yOffset);
-             }
-        }
-
-        for (int y = 0; y < hResolution; y++) {
-            final int curY = y * (wResolution + 1);
-            final int belowY = (y + 1) * (wResolution + 1);
-            for (int x = 0; x < wResolution; x++) {
-                int curV = curY + x;
-                int belowV = belowY + x;
-                tmb.addTriangle(curV, belowV, curV + 1);
-                tmb.addTriangle(belowV, belowV + 1, curV + 1);
-            }
-        }
-
-        return tmb.create(true);
-    }
-
-    /**
-     * Create a mesh with a single quad for the given width and height.
-     */
-    private Mesh getSingleMesh(float width, float height) {
-        Mesh.TriangleMeshBuilder tmb = new Mesh.TriangleMeshBuilder(mRS,
-                                           2, Mesh.TriangleMeshBuilder.TEXTURE_0);
-        float xOffset = width/2;
-        float yOffset = height/2;
-        tmb.setTexture(0, 0);
-        tmb.addVertex(-1.0f * xOffset, -1.0f * yOffset);
-        tmb.setTexture(1, 0);
-        tmb.addVertex(xOffset, -1.0f * yOffset);
-        tmb.setTexture(1, 1);
-        tmb.addVertex(xOffset, yOffset);
-        tmb.setTexture(0, 1);
-        tmb.addVertex(-1.0f * xOffset, yOffset);
-        tmb.addTriangle(0, 3, 1);
-        tmb.addTriangle(1, 3, 2);
-        return tmb.create(true);
-    }
-
-    private void initProgramStore() {
-        // Use stock the stock program store object
-        mProgStoreBlendNoneDepth = ProgramStore.BLEND_NONE_DEPTH_TEST(mRS);
-        mProgStoreBlendNone = ProgramStore.BLEND_NONE_DEPTH_NONE(mRS);
-
-        // Create a custom program store
-        ProgramStore.Builder builder = new ProgramStore.Builder(mRS);
-        builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
-        builder.setBlendFunc(ProgramStore.BlendSrcFunc.SRC_ALPHA,
-                             ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA);
-        builder.setDitherEnabled(false);
-        builder.setDepthMaskEnabled(false);
-        mProgStoreBlendAlpha = builder.create();
-
-        mProgStoreBlendAdd = BLEND_ADD_DEPTH_NONE(mRS);
-
-        mScript.set_gProgStoreBlendNoneDepth(mProgStoreBlendNoneDepth);
-
-        mScript.set_gProgStoreBlendNone(mProgStoreBlendNone);
-        mScript.set_gProgStoreBlendAlpha(mProgStoreBlendAlpha);
-        mScript.set_gProgStoreBlendAdd(mProgStoreBlendAdd);
-
-        // For GALAXY
-        builder = new ProgramStore.Builder(mRS);
-        builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO);
-        mRS.bindProgramStore(builder.create());
-
-        builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE);
-        mScript.set_gPSLights(builder.create());
-
-    }
-
     private void initProgramFragment() {
 
         ProgramFragmentFixedFunction.Builder texBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
@@ -329,64 +215,9 @@
         colBuilder.setVaryingColor(false);
         mProgFragmentColor = colBuilder.create();
 
-        mScript.set_gProgFragmentColor(mProgFragmentColor);
-
         mScript.set_gProgFragmentTexture(mProgFragmentTexture);
-
-
-
-        // For Galaxy live wallpaper drawing
-        ProgramFragmentFixedFunction.Builder builder = new ProgramFragmentFixedFunction.Builder(mRS);
-        builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
-                           ProgramFragmentFixedFunction.Builder.Format.RGB, 0);
-        ProgramFragment pfb = builder.create();
-        pfb.bindSampler(Sampler.WRAP_NEAREST(mRS), 0);
-        mScript.set_gPFBackground(pfb);
-
-        builder = new ProgramFragmentFixedFunction.Builder(mRS);
-        builder.setPointSpriteTexCoordinateReplacement(true);
-        builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.MODULATE,
-                           ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
-        builder.setVaryingColor(true);
-        ProgramFragment pfs = builder.create();
-        pfs.bindSampler(Sampler.WRAP_LINEAR_MIP_LINEAR(mRS), 0);
-        mScript.set_gPFStars(pfs);
-
     }
 
-    private Matrix4f getProjectionNormalized(int w, int h) {
-      // range -1,1 in the narrow axis at z = 0.
-      Matrix4f m1 = new Matrix4f();
-      Matrix4f m2 = new Matrix4f();
-
-      if(w > h) {
-          float aspect = ((float)w) / h;
-          m1.loadFrustum(-aspect,aspect,  -1,1,  1,100);
-      } else {
-          float aspect = ((float)h) / w;
-          m1.loadFrustum(-1,1, -aspect,aspect, 1,100);
-      }
-
-      m2.loadRotate(180, 0, 1, 0);
-      m1.loadMultiply(m1, m2);
-
-      m2.loadScale(-2, 2, 1);
-      m1.loadMultiply(m1, m2);
-
-      m2.loadTranslate(0, 0, 2);
-      m1.loadMultiply(m1, m2);
-      return m1;
-  }
-
-    private void updateProjectionMatrices() {
-      Matrix4f projNorm = getProjectionNormalized(mBenchmarkDimX, mBenchmarkDimY);
-      ScriptField_VpConsts.Item i = new ScriptField_VpConsts.Item();
-      i.Proj = projNorm;
-      i.MVP = projNorm;
-      mPvStarAlloc.set(i, 0, true);
-      mPvProjectionAlloc.setProjection(projNorm);
-  }
-
     private void initProgramVertex() {
         ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
         mProgVertex = pvb.create();
@@ -398,201 +229,6 @@
         mPVA.setProjection(proj);
 
         mScript.set_gProgVertex(mProgVertex);
-
-
-        // For galaxy live wallpaper
-        mPvStarAlloc = new ScriptField_VpConsts(mRS, 1);
-        mScript.bind_vpConstants(mPvStarAlloc);
-        mPvProjectionAlloc = new ProgramVertexFixedFunction.Constants(mRS);
-        updateProjectionMatrices();
-
-        pvb = new ProgramVertexFixedFunction.Builder(mRS);
-        ProgramVertex pvbp = pvb.create();
-        ((ProgramVertexFixedFunction)pvbp).bindConstants(mPvProjectionAlloc);
-        mScript.set_gPVBkProj(pvbp);
-
-        ProgramVertex.Builder sb = new ProgramVertex.Builder(mRS);
-        String t =  "varying vec4 varColor;\n" +
-                    "varying vec2 varTex0;\n" +
-                    "void main() {\n" +
-                    "  float dist = ATTRIB_position.y;\n" +
-                    "  float angle = ATTRIB_position.x;\n" +
-                    "  float x = dist * sin(angle);\n" +
-                    "  float y = dist * cos(angle) * 0.892;\n" +
-                    "  float p = dist * 5.5;\n" +
-                    "  float s = cos(p);\n" +
-                    "  float t = sin(p);\n" +
-                    "  vec4 pos;\n" +
-                    "  pos.x = t * x + s * y;\n" +
-                    "  pos.y = s * x - t * y;\n" +
-                    "  pos.z = ATTRIB_position.z;\n" +
-                    "  pos.w = 1.0;\n" +
-                    "  gl_Position = UNI_MVP * pos;\n" +
-                    "  gl_PointSize = ATTRIB_color.a * 10.0;\n" +
-                    "  varColor.rgb = ATTRIB_color.rgb;\n" +
-                    "  varColor.a = 1.0;\n" +
-                    "}\n";
-        sb.setShader(t);
-        sb.addInput(mParticlesMesh.getVertexAllocation(0).getType().getElement());
-        sb.addConstant(mPvStarAlloc.getType());
-        ProgramVertex pvs = sb.create();
-        pvs.bindConstants(mPvStarAlloc.getAllocation(), 0);
-        mScript.set_gPVStars(pvs);
-    }
-
-    private void initCustomShaders() {
-        mVSConst = new ScriptField_VertexShaderConstants_s(mRS, 1);
-        mFSConst = new ScriptField_FragentShaderConstants_s(mRS, 1);
-
-
-        mVSConstPixel = new ScriptField_VertexShaderConstants3_s(mRS, 1);
-        mFSConstPixel = new ScriptField_FragentShaderConstants3_s(mRS, 1);
-
-
-        // Initialize the shader builder
-        ProgramVertex.Builder pvbCustom = new ProgramVertex.Builder(mRS);
-        // Specify the resource that contains the shader string
-        pvbCustom.setShader(mRes, R.raw.shaderv);
-        // Use a script field to specify the input layout
-        pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
-        // Define the constant input layout
-        pvbCustom.addConstant(mVSConst.getAllocation().getType());
-        mProgVertexCustom = pvbCustom.create();
-        // Bind the source of constant data
-        mProgVertexCustom.bindConstants(mVSConst.getAllocation(), 0);
-
-        ProgramFragment.Builder pfbCustom = new ProgramFragment.Builder(mRS);
-        // Specify the resource that contains the shader string
-        pfbCustom.setShader(mRes, R.raw.shaderf);
-        // Tell the builder how many textures we have
-        pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
-        // Define the constant input layout
-        pfbCustom.addConstant(mFSConst.getAllocation().getType());
-        mProgFragmentCustom = pfbCustom.create();
-        // Bind the source of constant data
-        mProgFragmentCustom.bindConstants(mFSConst.getAllocation(), 0);
-
-        pvbCustom = new ProgramVertex.Builder(mRS);
-        pvbCustom.setShader(mRes, R.raw.shader2v);
-        pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
-        pvbCustom.addConstant(mVSConstPixel.getAllocation().getType());
-        mProgVertexPixelLight = pvbCustom.create();
-        mProgVertexPixelLight.bindConstants(mVSConstPixel.getAllocation(), 0);
-
-        pvbCustom = new ProgramVertex.Builder(mRS);
-        pvbCustom.setShader(mRes, R.raw.shader2movev);
-        pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
-        pvbCustom.addConstant(mVSConstPixel.getAllocation().getType());
-        mProgVertexPixelLightMove = pvbCustom.create();
-        mProgVertexPixelLightMove.bindConstants(mVSConstPixel.getAllocation(), 0);
-
-        pfbCustom = new ProgramFragment.Builder(mRS);
-        pfbCustom.setShader(mRes, R.raw.shader2f);
-        pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
-        pfbCustom.addConstant(mFSConstPixel.getAllocation().getType());
-        mProgFragmentPixelLight = pfbCustom.create();
-        mProgFragmentPixelLight.bindConstants(mFSConstPixel.getAllocation(), 0);
-
-        pfbCustom = new ProgramFragment.Builder(mRS);
-        pfbCustom.setShader(mRes, R.raw.multitexf);
-        for (int texCount = 0; texCount < 3; texCount ++) {
-            pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
-        }
-        mProgFragmentMultitex = pfbCustom.create();
-
-
-        mScript.set_gProgFragmentMultitex(mProgFragmentMultitex);
-    }
-
-    private Allocation loadTextureRGB(int id) {
-        return Allocation.createFromBitmapResource(mRS, mRes, id,
-                Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
-                Allocation.USAGE_GRAPHICS_TEXTURE);
-    }
-
-    private Allocation loadTextureARGB(int id) {
-        Bitmap b = BitmapFactory.decodeResource(mRes, id, mOptionsARGB);
-        return Allocation.createFromBitmap(mRS, b,
-                Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
-                Allocation.USAGE_GRAPHICS_TEXTURE);
-    }
-
-    private void loadImages() {
-        mTexTorus = loadTextureRGB(R.drawable.torusmap);
-        mTexOpaque = loadTextureRGB(R.drawable.data);
-        mTexTransparent = loadTextureARGB(R.drawable.leaf);
-        mTexChecker = loadTextureRGB(R.drawable.checker);
-        mTexGlobe = loadTextureRGB(R.drawable.globe);
-
-        mScript.set_gTexTorus(mTexTorus);
-        mScript.set_gTexOpaque(mTexOpaque);
-        mScript.set_gTexTransparent(mTexTransparent);
-        mScript.set_gTexChecker(mTexChecker);
-        mScript.set_gTexGlobe(mTexGlobe);
-
-        // For Galaxy live wallpaper
-        mScript.set_gTSpace(loadTextureRGB(R.drawable.space));
-        mScript.set_gTLight1(loadTextureRGB(R.drawable.light1));
-        mScript.set_gTFlares(loadTextureARGB(R.drawable.flares));
-    }
-
-    private void initFonts() {
-        // Sans font by family name
-        mFontSans = Font.create(mRS, mRes, "sans-serif", Font.Style.NORMAL, 8);
-        mFontSerif = Font.create(mRS, mRes, "serif", Font.Style.NORMAL, 8);
-        // Create fonts by family and style
-
-        mTextAlloc = Allocation.createFromString(mRS, "String from allocation", Allocation.USAGE_SCRIPT);
-
-        mScript.set_gFontSans(mFontSans);
-        mScript.set_gFontSerif(mFontSerif);
-    }
-
-    private void createParticlesMesh() {
-        ScriptField_Particle p = new ScriptField_Particle(mRS, PARTICLES_COUNT);
-
-        final Mesh.AllocationBuilder meshBuilder = new Mesh.AllocationBuilder(mRS);
-        meshBuilder.addVertexAllocation(p.getAllocation());
-        final int vertexSlot = meshBuilder.getCurrentVertexTypeIndex();
-        meshBuilder.addIndexSetType(Primitive.POINT);
-        mParticlesMesh = meshBuilder.create();
-
-        mScript.set_gParticlesMesh(mParticlesMesh);
-        mScript.bind_Particles(p);
-    }
-
-    private void initMesh() {
-        m10by10Mesh = getMbyNMesh(mBenchmarkDimX, mBenchmarkDimY, 10, 10);
-        mScript.set_g10by10Mesh(m10by10Mesh);
-        m100by100Mesh = getMbyNMesh(mBenchmarkDimX, mBenchmarkDimY, 100, 100);
-        mScript.set_g100by100Mesh(m100by100Mesh);
-        mWbyHMesh= getMbyNMesh(mBenchmarkDimX, mBenchmarkDimY, mBenchmarkDimX/4, mBenchmarkDimY/4);
-        mScript.set_gWbyHMesh(mWbyHMesh);
-        mSingleMesh = getSingleMesh(1, 1);  // a unit size mesh
-        mScript.set_gSingleMesh(mSingleMesh);
-
-        FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.torus);
-        FileA3D.IndexEntry entry = model.getIndexEntry(0);
-        if (entry == null || entry.getEntryType() != FileA3D.EntryType.MESH) {
-            Log.e("rs", "could not load model");
-        } else {
-            mTorus = (Mesh)entry.getObject();
-        }
-
-        createParticlesMesh();
-    }
-
-    private void initSamplers() {
-        mScript.set_gLinearClamp(Sampler.CLAMP_LINEAR(mRS));
-        mScript.set_gLinearWrap(Sampler.WRAP_LINEAR(mRS));
-        mScript.set_gMipLinearWrap(Sampler.WRAP_LINEAR_MIP_LINEAR(mRS));
-        mScript.set_gNearestClamp(Sampler.CLAMP_NEAREST(mRS));
-    }
-
-    private void initProgramRaster() {
-        mScript.set_gCullBack(ProgramRaster.CULL_BACK(mRS));
-        mScript.set_gCullFront(ProgramRaster.CULL_FRONT(mRS));
-        mScript.set_gCullNone(ProgramRaster.CULL_NONE(mRS));
     }
 
     private int strlen(byte[] array) {
@@ -606,16 +242,6 @@
     private void prepareTestData() {
         mTestNames = new String[mMaxModes];
         mLocalTestResults = new float[mMaxModes];
-        int scratchSize = 1024;
-        Allocation scratch = Allocation.createSized(mRS, Element.U8(mRS), scratchSize);
-        byte[] tmp = new byte[scratchSize];
-        mScript.bind_gStringBuffer(scratch);
-        for (int i = 0; i < mMaxModes; i ++) {
-            mScript.invoke_getTestName(i);
-            scratch.copyTo(tmp);
-            int len = strlen(tmp);
-            mTestNames[i] = new String(tmp, 0, len);
-        }
     }
 
     public void setDebugMode(int num) {
@@ -626,55 +252,20 @@
         mScript.invoke_setBenchmarkMode();
     }
 
-    void initTextScript() {
-        mTextScript = new ScriptC_text_test(mRS, mRes, R.raw.text_test);
-        mTextScript.set_gFontSans(mFontSans);
-        mTextScript.set_gFontSerif(mFontSerif);
-    }
-
-    void initTorusScript() {
-        mTorusScript = new ScriptC_torus_test(mRS, mRes, R.raw.torus_test);
-        mTorusScript.set_gCullFront(ProgramRaster.CULL_FRONT(mRS));
-        mTorusScript.set_gCullBack(ProgramRaster.CULL_BACK(mRS));
-        mTorusScript.set_gLinearClamp(Sampler.CLAMP_LINEAR(mRS));
-        mTorusScript.set_gTorusMesh(mTorus);
-        mTorusScript.set_gTexTorus(mTexTorus);
-        mTorusScript.set_gProgVertexCustom(mProgVertexCustom);
-        mTorusScript.set_gProgFragmentCustom(mProgFragmentCustom);
-        mTorusScript.set_gProgVertexPixelLight(mProgVertexPixelLight);
-        mTorusScript.set_gProgVertexPixelLightMove(mProgVertexPixelLightMove);
-        mTorusScript.set_gProgFragmentPixelLight(mProgFragmentPixelLight);
-        mTorusScript.bind_gVSConstPixel(mVSConstPixel);
-        mTorusScript.bind_gFSConstPixel(mFSConstPixel);
-        mTorusScript.bind_gVSConstants(mVSConst);
-        mTorusScript.bind_gFSConstants(mFSConst);
-        mTorusScript.set_gProgVertex(mProgVertex);
-        mTorusScript.set_gProgFragmentTexture(mProgFragmentTexture);
-        mTorusScript.set_gProgFragmentColor(mProgFragmentColor);
-        mTorusScript.set_gProgStoreBlendNoneDepth(mProgStoreBlendNoneDepth);
-    }
-
     private void initRS() {
 
         mScript = new ScriptC_rsbench(mRS, mRes, R.raw.rsbench);
-
+        mRS.bindRootScript(mScript);
 
         mRS.setMessageHandler(mRsMessage);
 
-        mMaxModes = mScript.get_gMaxModes();
         mScript.set_gMaxLoops(mLoops);
 
         prepareTestData();
 
-        initSamplers();
-        initMesh();
         initProgramVertex();
-        initProgramStore();
         initProgramFragment();
-        initFonts();
-        loadImages();
-        initProgramRaster();
-        initCustomShaders();
+        mScript.set_gFontSerif(Font.create(mRS, mRes, "serif", Font.Style.NORMAL, 8));
 
         Type.Builder b = new Type.Builder(mRS, Element.RGBA_8888(mRS));
         b.setX(mBenchmarkDimX).setY(mBenchmarkDimY);
@@ -692,41 +283,30 @@
                                            b.create(),
                                            Allocation.USAGE_GRAPHICS_RENDER_TARGET);
         mScript.set_gRenderBufferDepth(offscreen);
+        mScript.set_gLinearClamp(Sampler.CLAMP_LINEAR(mRS));
 
-        mTextureAllocs = new ScriptField_ListAllocs_s(mRS, 100);
-        for (int i = 0; i < 100; i++) {
-            ScriptField_ListAllocs_s.Item texElem = new ScriptField_ListAllocs_s.Item();
-            texElem.item = loadTextureRGB(R.drawable.globe);
-            mTextureAllocs.set(texElem, i, false);
+        RsBenchBaseTest test = new TextTest();
+        if (test.init(mRS, mRes)) {
+            appendTests(test);
         }
-        mTextureAllocs.copyAll();
-        mScript.bind_gTexList100(mTextureAllocs);
-
-        mSampleTextAllocs = new ScriptField_ListAllocs_s(mRS, 100);
-        for (int i = 0; i < 100; i++) {
-            ScriptField_ListAllocs_s.Item textElem = new ScriptField_ListAllocs_s.Item();
-            textElem.item = Allocation.createFromString(mRS, SAMPLE_TEXT, Allocation.USAGE_SCRIPT);
-            mSampleTextAllocs.set(textElem, i, false);
+        test = new FillTest();
+        if (test.init(mRS, mRes)) {
+            appendTests(test);
         }
-        mSampleTextAllocs.copyAll();
-        mScript.bind_gSampleTextList100(mSampleTextAllocs);
-
-        mSampleListViewAllocs = new ScriptField_ListAllocs_s(mRS, 1000);
-        for (int i = 0; i < 1000; i++) {
-            ScriptField_ListAllocs_s.Item textElem = new ScriptField_ListAllocs_s.Item();
-            textElem.item = Allocation.createFromString(mRS, LIST_TEXT, Allocation.USAGE_SCRIPT);
-            mSampleListViewAllocs.set(textElem, i, false);
+        test = new MeshTest();
+        if (test.init(mRS, mRes)) {
+            appendTests(test);
         }
-        mSampleListViewAllocs.copyAll();
-        mScript.bind_gListViewText(mSampleListViewAllocs);
+        test = new TorusTest();
+        if (test.init(mRS, mRes)) {
+            appendTests(test);
+        }
+        test = new UiTest();
+        if (test.init(mRS, mRes)) {
+            appendTests(test);
+        }
+        createTestAllocation();
 
-        initTextScript();
-        initTorusScript();
-
-        mScript.set_gFontScript(mTextScript);
-        mScript.set_gTorusScript(mTorusScript);
-        mScript.set_gDummyAlloc(Allocation.createSized(mRS, Element.I32(mRS), 1));
-
-        mRS.bindRootScript(mScript);
+        mScript.set_gLoadComplete(true);
     }
 }
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchView.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchView.java
index 61aa3e1..efcb463 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchView.java
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchView.java
@@ -71,24 +71,6 @@
         }
     }
 
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        return super.onKeyDown(keyCode, event);
-    }
-
-
-    @Override
-    public boolean onTouchEvent(MotionEvent ev) {
-        boolean ret = false;
-        int act = ev.getAction();
-        if (act == ev.ACTION_DOWN) {
-            mRender.onActionDown((int)ev.getX(), (int)ev.getY());
-            ret = true;
-        }
-
-        return ret;
-    }
-
     /**
      * Set the total number of loops the benchmark tests will run
      * before the test results are collected.
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/TextTest.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/TextTest.java
new file mode 100644
index 0000000..65290e7
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/TextTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.perftest;
+
+import android.os.Environment;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+import android.util.Log;
+
+
+public class TextTest implements RsBenchBaseTest{
+
+    private static final String TAG = "TextTest";
+    private RenderScriptGL mRS;
+    private Resources mRes;
+
+    private ScriptC_text_test mTextScript;
+    ScriptField_TestScripts_s.Item[] mTests;
+
+    private final String[] mNames = {
+        "Fill screen with text 1 time",
+        "Fill screen with text 3 times",
+        "Fill screen with text 5 times"
+    };
+
+    public TextTest() {
+    }
+
+    void addTest(int index, int fillNum) {
+        mTests[index] = new ScriptField_TestScripts_s.Item();
+        mTests[index].testScript = mTextScript;
+        mTests[index].testName = Allocation.createFromString(mRS,
+                                                             mNames[index],
+                                                             Allocation.USAGE_SCRIPT);
+
+        ScriptField_TextTestData_s.Item dataItem = new ScriptField_TextTestData_s.Item();
+        dataItem.fillNum = fillNum;
+        ScriptField_TextTestData_s testData = new ScriptField_TextTestData_s(mRS, 1);
+        testData.set(dataItem, 0, true);
+        mTests[index].testData = testData.getAllocation();
+    }
+
+    public boolean init(RenderScriptGL rs, Resources res) {
+        mRS = rs;
+        mRes = res;
+        initTextScript();
+        mTests = new ScriptField_TestScripts_s.Item[mNames.length];
+
+        int index = 0;
+        addTest(index++, 1 /*fillNum*/);
+        addTest(index++, 3 /*fillNum*/);
+        addTest(index++, 5 /*fillNum*/);
+
+        return true;
+    }
+
+    public ScriptField_TestScripts_s.Item[] getTests() {
+        return mTests;
+    }
+
+    public String[] getTestNames() {
+        return mNames;
+    }
+
+    void initTextScript() {
+        mTextScript = new ScriptC_text_test(mRS, mRes, R.raw.text_test);
+        mTextScript.set_gFontSans(Font.create(mRS, mRes, "sans-serif", Font.Style.NORMAL, 8));
+        mTextScript.set_gFontSerif(Font.create(mRS, mRes, "serif", Font.Style.NORMAL, 8));
+    }
+}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/TorusTest.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/TorusTest.java
new file mode 100644
index 0000000..d785dc1
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/TorusTest.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.perftest;
+
+import android.os.Environment;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.renderscript.*;
+import android.renderscript.Element.DataKind;
+import android.renderscript.Element.DataType;
+import android.renderscript.Allocation.MipmapControl;
+import android.renderscript.Program.TextureType;
+import android.renderscript.RenderScript.RSMessageHandler;
+import android.renderscript.Mesh.Primitive;
+import android.renderscript.Matrix4f;
+import android.renderscript.ProgramVertexFixedFunction;
+
+import android.util.Log;
+
+
+public class TorusTest implements RsBenchBaseTest{
+
+    private static final String TAG = "TorusTest";
+    private RenderScriptGL mRS;
+    private Resources mRes;
+
+    private ProgramStore mProgStoreBlendNoneDepth;
+    private ProgramStore mProgStoreBlendNone;
+    private ProgramStore mProgStoreBlendAlpha;
+
+    private ProgramFragment mProgFragmentTexture;
+    private ProgramFragment mProgFragmentColor;
+
+    private ProgramVertex mProgVertex;
+    private ProgramVertexFixedFunction.Constants mPVA;
+    private ProgramVertexFixedFunction.Constants mPvProjectionAlloc;
+
+    // Custom shaders
+    private ProgramVertex mProgVertexCustom;
+    private ProgramFragment mProgFragmentCustom;
+    private ProgramFragment mProgFragmentMultitex;
+    private ProgramVertex mProgVertexPixelLight;
+    private ProgramVertex mProgVertexPixelLightMove;
+    private ProgramFragment mProgFragmentPixelLight;
+    private ScriptField_VertexShaderConstants_s mVSConst;
+    private ScriptField_FragentShaderConstants_s mFSConst;
+    private ScriptField_VertexShaderConstants3_s mVSConstPixel;
+    private ScriptField_FragentShaderConstants3_s mFSConstPixel;
+
+    private Allocation mTexTorus;
+    private Mesh mTorus;
+
+    private ScriptC_torus_test mTorusScript;
+
+    private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
+
+    ScriptField_TestScripts_s.Item[] mTests;
+
+    private final String[] mNames = {
+        "Geo test 25.6k flat color",
+        "Geo test 51.2k flat color",
+        "Geo test 204.8k small tries flat color",
+        "Geo test 25.6k single texture",
+        "Geo test 51.2k single texture",
+        "Geo test 204.8k small tries single texture",
+        "Geo test 25.6k geo heavy vertex",
+        "Geo test 51.2k geo heavy vertex",
+        "Geo test 204.8k geo raster load heavy vertex",
+        "Geo test 25.6k heavy fragment",
+        "Geo test 51.2k heavy fragment",
+        "Geo test 204.8k small tries heavy fragment",
+        "Geo test 25.6k heavy fragment heavy vertex",
+        "Geo test 51.2k heavy fragment heavy vertex",
+        "Geo test 204.8k small tries heavy fragment heavy vertex"
+    };
+
+    public TorusTest() {
+    }
+
+    void addTest(int index, int testId, int user1, int user2) {
+        mTests[index] = new ScriptField_TestScripts_s.Item();
+        mTests[index].testScript = mTorusScript;
+        mTests[index].testName = Allocation.createFromString(mRS,
+                                                             mNames[index],
+                                                             Allocation.USAGE_SCRIPT);
+
+        ScriptField_TorusTestData_s.Item dataItem = new ScriptField_TorusTestData_s.Item();
+        dataItem.testId = testId;
+        dataItem.user1 = user1;
+        dataItem.user2 = user2;
+        ScriptField_TorusTestData_s testData = new ScriptField_TorusTestData_s(mRS, 1);
+        testData.set(dataItem, 0, true);
+        mTests[index].testData = testData.getAllocation();
+    }
+
+    public boolean init(RenderScriptGL rs, Resources res) {
+        mRS = rs;
+        mRes = res;
+        initCustomShaders();
+        loadImages();
+        initMesh();
+        initTorusScript();
+        mTests = new ScriptField_TestScripts_s.Item[mNames.length];
+
+        int index = 0;
+        addTest(index++, 0, 0 /*useTexture*/, 1 /*numMeshes*/);
+        addTest(index++, 0, 0 /*useTexture*/, 2 /*numMeshes*/);
+        addTest(index++, 0, 0 /*useTexture*/, 8 /*numMeshes*/);
+        addTest(index++, 0, 1 /*useTexture*/, 1 /*numMeshes*/);
+        addTest(index++, 0, 1 /*useTexture*/, 2 /*numMeshes*/);
+        addTest(index++, 0, 1 /*useTexture*/, 8 /*numMeshes*/);
+
+        // Secont test
+        addTest(index++, 1, 1 /*numMeshes*/, 0 /*unused*/);
+        addTest(index++, 1, 2 /*numMeshes*/, 0 /*unused*/);
+        addTest(index++, 1, 8 /*numMeshes*/, 0 /*unused*/);
+
+        // Third test
+        addTest(index++, 2, 1 /*numMeshes*/, 0 /*heavyVertex*/);
+        addTest(index++, 2, 2 /*numMeshes*/, 0 /*heavyVertex*/);
+        addTest(index++, 2, 8 /*numMeshes*/, 0 /*heavyVertex*/);
+        addTest(index++, 2, 1 /*numMeshes*/, 1 /*heavyVertex*/);
+        addTest(index++, 2, 2 /*numMeshes*/, 1 /*heavyVertex*/);
+        addTest(index++, 2, 8 /*numMeshes*/, 1 /*heavyVertex*/);
+
+        return true;
+    }
+
+    public ScriptField_TestScripts_s.Item[] getTests() {
+        return mTests;
+    }
+
+    public String[] getTestNames() {
+        return mNames;
+    }
+
+    private void initCustomShaders() {
+        mVSConst = new ScriptField_VertexShaderConstants_s(mRS, 1);
+        mFSConst = new ScriptField_FragentShaderConstants_s(mRS, 1);
+
+        mVSConstPixel = new ScriptField_VertexShaderConstants3_s(mRS, 1);
+        mFSConstPixel = new ScriptField_FragentShaderConstants3_s(mRS, 1);
+
+        // Initialize the shader builder
+        ProgramVertex.Builder pvbCustom = new ProgramVertex.Builder(mRS);
+        // Specify the resource that contains the shader string
+        pvbCustom.setShader(mRes, R.raw.shaderv);
+        // Use a script field to specify the input layout
+        pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
+        // Define the constant input layout
+        pvbCustom.addConstant(mVSConst.getAllocation().getType());
+        mProgVertexCustom = pvbCustom.create();
+        // Bind the source of constant data
+        mProgVertexCustom.bindConstants(mVSConst.getAllocation(), 0);
+
+        ProgramFragment.Builder pfbCustom = new ProgramFragment.Builder(mRS);
+        // Specify the resource that contains the shader string
+        pfbCustom.setShader(mRes, R.raw.shaderf);
+        // Tell the builder how many textures we have
+        pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
+        // Define the constant input layout
+        pfbCustom.addConstant(mFSConst.getAllocation().getType());
+        mProgFragmentCustom = pfbCustom.create();
+        // Bind the source of constant data
+        mProgFragmentCustom.bindConstants(mFSConst.getAllocation(), 0);
+
+        pvbCustom = new ProgramVertex.Builder(mRS);
+        pvbCustom.setShader(mRes, R.raw.shader2v);
+        pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
+        pvbCustom.addConstant(mVSConstPixel.getAllocation().getType());
+        mProgVertexPixelLight = pvbCustom.create();
+        mProgVertexPixelLight.bindConstants(mVSConstPixel.getAllocation(), 0);
+
+        pvbCustom = new ProgramVertex.Builder(mRS);
+        pvbCustom.setShader(mRes, R.raw.shader2movev);
+        pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
+        pvbCustom.addConstant(mVSConstPixel.getAllocation().getType());
+        mProgVertexPixelLightMove = pvbCustom.create();
+        mProgVertexPixelLightMove.bindConstants(mVSConstPixel.getAllocation(), 0);
+
+        pfbCustom = new ProgramFragment.Builder(mRS);
+        pfbCustom.setShader(mRes, R.raw.shader2f);
+        pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
+        pfbCustom.addConstant(mFSConstPixel.getAllocation().getType());
+        mProgFragmentPixelLight = pfbCustom.create();
+        mProgFragmentPixelLight.bindConstants(mFSConstPixel.getAllocation(), 0);
+
+        pfbCustom = new ProgramFragment.Builder(mRS);
+        pfbCustom.setShader(mRes, R.raw.multitexf);
+        for (int texCount = 0; texCount < 3; texCount ++) {
+            pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
+        }
+        mProgFragmentMultitex = pfbCustom.create();
+
+        ProgramFragmentFixedFunction.Builder colBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
+        colBuilder.setVaryingColor(false);
+        mProgFragmentColor = colBuilder.create();
+
+        ProgramFragmentFixedFunction.Builder texBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
+        texBuilder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
+                              ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
+        mProgFragmentTexture = texBuilder.create();
+
+        ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
+        mProgVertex = pvb.create();
+        ProgramVertexFixedFunction.Constants PVA = new ProgramVertexFixedFunction.Constants(mRS);
+        ((ProgramVertexFixedFunction)mProgVertex).bindConstants(PVA);
+        Matrix4f proj = new Matrix4f();
+        proj.loadOrthoWindow(1280, 720);
+        PVA.setProjection(proj);
+    }
+
+    private Allocation loadTextureRGB(int id) {
+        return Allocation.createFromBitmapResource(mRS, mRes, id,
+                Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
+                Allocation.USAGE_GRAPHICS_TEXTURE);
+    }
+
+    private void loadImages() {
+        mTexTorus = loadTextureRGB(R.drawable.torusmap);
+    }
+
+    private void initMesh() {
+        FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.torus);
+        FileA3D.IndexEntry entry = model.getIndexEntry(0);
+        if (entry == null || entry.getEntryType() != FileA3D.EntryType.MESH) {
+            Log.e("rs", "could not load model");
+        } else {
+            mTorus = (Mesh)entry.getObject();
+        }
+    }
+
+    void initTorusScript() {
+        mTorusScript = new ScriptC_torus_test(mRS, mRes, R.raw.torus_test);
+        mTorusScript.set_gCullFront(ProgramRaster.CULL_FRONT(mRS));
+        mTorusScript.set_gCullBack(ProgramRaster.CULL_BACK(mRS));
+        mTorusScript.set_gLinearClamp(Sampler.CLAMP_LINEAR(mRS));
+        mTorusScript.set_gTorusMesh(mTorus);
+        mTorusScript.set_gTexTorus(mTexTorus);
+        mTorusScript.set_gProgVertexCustom(mProgVertexCustom);
+        mTorusScript.set_gProgFragmentCustom(mProgFragmentCustom);
+        mTorusScript.set_gProgVertexPixelLight(mProgVertexPixelLight);
+        mTorusScript.set_gProgVertexPixelLightMove(mProgVertexPixelLightMove);
+        mTorusScript.set_gProgFragmentPixelLight(mProgFragmentPixelLight);
+        mTorusScript.bind_gVSConstPixel(mVSConstPixel);
+        mTorusScript.bind_gFSConstPixel(mFSConstPixel);
+        mTorusScript.bind_gVSConstants(mVSConst);
+        mTorusScript.bind_gFSConstants(mFSConst);
+        mTorusScript.set_gProgVertex(mProgVertex);
+        mTorusScript.set_gProgFragmentTexture(mProgFragmentTexture);
+        mTorusScript.set_gProgFragmentColor(mProgFragmentColor);
+        mTorusScript.set_gProgStoreBlendNoneDepth(mProgStoreBlendNoneDepth);
+    }
+}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/UiTest.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/UiTest.java
new file mode 100644
index 0000000..cca237e
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/UiTest.java
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.perftest;
+
+import android.os.Environment;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.renderscript.*;
+import android.renderscript.Element.DataKind;
+import android.renderscript.Element.DataType;
+import android.renderscript.Allocation.MipmapControl;
+import android.renderscript.Program.TextureType;
+import android.renderscript.ProgramStore.DepthFunc;
+import android.renderscript.ProgramStore.BlendSrcFunc;
+import android.renderscript.ProgramStore.BlendDstFunc;
+import android.renderscript.RenderScript.RSMessageHandler;
+import android.renderscript.Mesh.Primitive;
+import android.renderscript.Matrix4f;
+import android.renderscript.ProgramVertexFixedFunction;
+
+import android.util.Log;
+
+
+public class UiTest implements RsBenchBaseTest{
+
+    private static final String TAG = "UiTest";
+    private static final String SAMPLE_TEXT = "Bench Test";
+    private static final String LIST_TEXT =
+      "This is a sample list of text to show in the list view";
+    private static int PARTICLES_COUNT = 12000;
+
+    private RenderScriptGL mRS;
+    private Resources mRes;
+
+    Font mFontSans;
+
+    private ScriptField_ListAllocs_s mTextureAllocs;
+    private ScriptField_ListAllocs_s mSampleTextAllocs;
+    private ScriptField_ListAllocs_s mSampleListViewAllocs;
+    private ScriptField_VpConsts mPvStarAlloc;
+    private ProgramVertexFixedFunction.Constants mPvProjectionAlloc;
+
+    private Mesh mSingleMesh;
+    private Mesh mParticlesMesh;
+
+    private ScriptC_ui_test mUiScript;
+
+    private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
+
+    ScriptField_TestScripts_s.Item[] mTests;
+
+    private final String[] mNames = {
+        "UI test with icon display 10 by 10",
+        "UI test with icon display 100 by 100",
+        "UI test with image and text display 3 pages",
+        "UI test with image and text display 5 pages",
+        "UI test with list view",
+        "UI test with live wallpaper"
+    };
+
+    public UiTest() {
+    }
+
+    void addTest(int index, int testId, int user1, int user2, int user3) {
+        mTests[index] = new ScriptField_TestScripts_s.Item();
+        mTests[index].testScript = mUiScript;
+        mTests[index].testName = Allocation.createFromString(mRS,
+                                                             mNames[index],
+                                                             Allocation.USAGE_SCRIPT);
+
+        ScriptField_UiTestData_s.Item dataItem = new ScriptField_UiTestData_s.Item();
+        dataItem.testId = testId;
+        dataItem.user1 = user1;
+        dataItem.user2 = user2;
+        dataItem.user3 = user3;
+        ScriptField_UiTestData_s testData = new ScriptField_UiTestData_s(mRS, 1);
+        testData.set(dataItem, 0, true);
+        mTests[index].testData = testData.getAllocation();
+    }
+
+    public boolean init(RenderScriptGL rs, Resources res) {
+        mRS = rs;
+        mRes = res;
+        mFontSans = Font.create(mRS, mRes, "sans-serif", Font.Style.NORMAL, 8);
+        mSingleMesh = getSingleMesh(1, 1);  // a unit size mesh
+
+        initUiScript();
+        mTests = new ScriptField_TestScripts_s.Item[mNames.length];
+
+        int index = 0;
+
+        addTest(index++, 0, 0 /*meshMode*/, 0 /*unused*/, 0 /*unused*/);
+        addTest(index++, 0, 1 /*meshMode*/, 0 /*unused*/, 0 /*unused*/);
+        addTest(index++, 1, 7 /*wResolution*/, 5 /*hResolution*/, 0 /*meshMode*/);
+        addTest(index++, 1, 7 /*wResolution*/, 5 /*hResolution*/, 1 /*meshMode*/);
+        addTest(index++, 2, 0 /*unused*/, 0 /*unused*/, 0 /*unused*/);
+        addTest(index++, 3, 7 /*wResolution*/, 5 /*hResolution*/, 0 /*unused*/);
+
+        return true;
+    }
+
+    public ScriptField_TestScripts_s.Item[] getTests() {
+        return mTests;
+    }
+
+    public String[] getTestNames() {
+        return mNames;
+    }
+
+    private Allocation loadTextureRGB(int id) {
+        return Allocation.createFromBitmapResource(mRS, mRes, id,
+                Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
+                Allocation.USAGE_GRAPHICS_TEXTURE);
+    }
+
+    private Allocation loadTextureARGB(int id) {
+        Bitmap b = BitmapFactory.decodeResource(mRes, id, mOptionsARGB);
+        return Allocation.createFromBitmap(mRS, b,
+                Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
+                Allocation.USAGE_GRAPHICS_TEXTURE);
+    }
+
+    private void createParticlesMesh() {
+        ScriptField_Particle p = new ScriptField_Particle(mRS, PARTICLES_COUNT);
+
+        final Mesh.AllocationBuilder meshBuilder = new Mesh.AllocationBuilder(mRS);
+        meshBuilder.addVertexAllocation(p.getAllocation());
+        final int vertexSlot = meshBuilder.getCurrentVertexTypeIndex();
+        meshBuilder.addIndexSetType(Primitive.POINT);
+        mParticlesMesh = meshBuilder.create();
+
+        mUiScript.set_gParticlesMesh(mParticlesMesh);
+        mUiScript.bind_Particles(p);
+    }
+
+    /**
+     * Create a mesh with a single quad for the given width and height.
+     */
+    private Mesh getSingleMesh(float width, float height) {
+        Mesh.TriangleMeshBuilder tmb = new Mesh.TriangleMeshBuilder(mRS,
+                                           2, Mesh.TriangleMeshBuilder.TEXTURE_0);
+        float xOffset = width/2;
+        float yOffset = height/2;
+        tmb.setTexture(0, 0);
+        tmb.addVertex(-1.0f * xOffset, -1.0f * yOffset);
+        tmb.setTexture(1, 0);
+        tmb.addVertex(xOffset, -1.0f * yOffset);
+        tmb.setTexture(1, 1);
+        tmb.addVertex(xOffset, yOffset);
+        tmb.setTexture(0, 1);
+        tmb.addVertex(-1.0f * xOffset, yOffset);
+        tmb.addTriangle(0, 3, 1);
+        tmb.addTriangle(1, 3, 2);
+        return tmb.create(true);
+    }
+
+    private Matrix4f getProjectionNormalized(int w, int h) {
+        // range -1,1 in the narrow axis at z = 0.
+        Matrix4f m1 = new Matrix4f();
+        Matrix4f m2 = new Matrix4f();
+
+        if(w > h) {
+            float aspect = ((float)w) / h;
+            m1.loadFrustum(-aspect,aspect,  -1,1,  1,100);
+        } else {
+            float aspect = ((float)h) / w;
+            m1.loadFrustum(-1,1, -aspect,aspect, 1,100);
+        }
+
+        m2.loadRotate(180, 0, 1, 0);
+        m1.loadMultiply(m1, m2);
+
+        m2.loadScale(-2, 2, 1);
+        m1.loadMultiply(m1, m2);
+
+        m2.loadTranslate(0, 0, 2);
+        m1.loadMultiply(m1, m2);
+        return m1;
+    }
+
+    private void updateProjectionMatrices() {
+        Matrix4f projNorm = getProjectionNormalized(1280, 720);
+        ScriptField_VpConsts.Item i = new ScriptField_VpConsts.Item();
+        i.Proj = projNorm;
+        i.MVP = projNorm;
+        mPvStarAlloc.set(i, 0, true);
+        mPvProjectionAlloc.setProjection(projNorm);
+    }
+
+    void initUiScript() {
+        mUiScript = new ScriptC_ui_test(mRS, mRes, R.raw.ui_test);
+
+        ProgramFragmentFixedFunction.Builder colBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
+        colBuilder.setVaryingColor(false);
+        ProgramFragmentFixedFunction.Builder texBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
+        texBuilder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
+                              ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
+
+        ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
+        ProgramVertexFixedFunction progVertex = pvb.create();
+        ProgramVertexFixedFunction.Constants PVA = new ProgramVertexFixedFunction.Constants(mRS);
+        ((ProgramVertexFixedFunction)progVertex).bindConstants(PVA);
+        Matrix4f proj = new Matrix4f();
+        proj.loadOrthoWindow(1280, 720);
+        PVA.setProjection(proj);
+
+        mUiScript.set_gProgVertex(progVertex);
+        mUiScript.set_gProgFragmentColor(colBuilder.create());
+        mUiScript.set_gProgFragmentTexture(texBuilder.create());
+        mUiScript.set_gProgStoreBlendAlpha(ProgramStore.BLEND_ALPHA_DEPTH_NONE(mRS));
+
+        mUiScript.set_gLinearClamp(Sampler.CLAMP_LINEAR(mRS));
+
+        mUiScript.set_gTexTorus(loadTextureRGB(R.drawable.torusmap));
+        mUiScript.set_gTexOpaque(loadTextureRGB(R.drawable.data));
+        mUiScript.set_gTexGlobe(loadTextureRGB(R.drawable.globe));
+        mUiScript.set_gSingleMesh(mSingleMesh);
+
+        // For GALAXY
+        ProgramStore.Builder psb = new ProgramStore.Builder(mRS);
+        psb.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO);
+        mRS.bindProgramStore(psb.create());
+
+        psb.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE);
+        mUiScript.set_gPSLights(psb.create());
+
+        // For Galaxy live wallpaper drawing
+        ProgramFragmentFixedFunction.Builder builder = new ProgramFragmentFixedFunction.Builder(mRS);
+        builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
+                           ProgramFragmentFixedFunction.Builder.Format.RGB, 0);
+        ProgramFragment pfb = builder.create();
+        pfb.bindSampler(Sampler.WRAP_NEAREST(mRS), 0);
+        mUiScript.set_gPFBackground(pfb);
+
+        builder = new ProgramFragmentFixedFunction.Builder(mRS);
+        builder.setPointSpriteTexCoordinateReplacement(true);
+        builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.MODULATE,
+                           ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
+        builder.setVaryingColor(true);
+        ProgramFragment pfs = builder.create();
+        pfs.bindSampler(Sampler.WRAP_LINEAR_MIP_LINEAR(mRS), 0);
+        mUiScript.set_gPFStars(pfs);
+
+        mTextureAllocs = new ScriptField_ListAllocs_s(mRS, 100);
+        for (int i = 0; i < 100; i++) {
+            ScriptField_ListAllocs_s.Item texElem = new ScriptField_ListAllocs_s.Item();
+            texElem.item = loadTextureRGB(R.drawable.globe);
+            mTextureAllocs.set(texElem, i, false);
+        }
+        mTextureAllocs.copyAll();
+        mUiScript.bind_gTexList100(mTextureAllocs);
+
+        mSampleTextAllocs = new ScriptField_ListAllocs_s(mRS, 100);
+        for (int i = 0; i < 100; i++) {
+            ScriptField_ListAllocs_s.Item textElem = new ScriptField_ListAllocs_s.Item();
+            textElem.item = Allocation.createFromString(mRS, SAMPLE_TEXT, Allocation.USAGE_SCRIPT);
+            mSampleTextAllocs.set(textElem, i, false);
+        }
+        mSampleTextAllocs.copyAll();
+        mUiScript.bind_gSampleTextList100(mSampleTextAllocs);
+
+        mSampleListViewAllocs = new ScriptField_ListAllocs_s(mRS, 1000);
+        for (int i = 0; i < 1000; i++) {
+            ScriptField_ListAllocs_s.Item textElem = new ScriptField_ListAllocs_s.Item();
+            textElem.item = Allocation.createFromString(mRS, LIST_TEXT, Allocation.USAGE_SCRIPT);
+            mSampleListViewAllocs.set(textElem, i, false);
+        }
+        mSampleListViewAllocs.copyAll();
+        mUiScript.bind_gListViewText(mSampleListViewAllocs);
+
+        // For galaxy live wallpaper
+        mPvStarAlloc = new ScriptField_VpConsts(mRS, 1);
+        mUiScript.bind_vpConstants(mPvStarAlloc);
+        mPvProjectionAlloc = new ProgramVertexFixedFunction.Constants(mRS);
+        updateProjectionMatrices();
+
+        pvb = new ProgramVertexFixedFunction.Builder(mRS);
+        ProgramVertex pvbp = pvb.create();
+        ((ProgramVertexFixedFunction)pvbp).bindConstants(mPvProjectionAlloc);
+        mUiScript.set_gPVBkProj(pvbp);
+
+        createParticlesMesh();
+
+        ProgramVertex.Builder sb = new ProgramVertex.Builder(mRS);
+        String t =  "varying vec4 varColor;\n" +
+                    "varying vec2 varTex0;\n" +
+                    "void main() {\n" +
+                    "  float dist = ATTRIB_position.y;\n" +
+                    "  float angle = ATTRIB_position.x;\n" +
+                    "  float x = dist * sin(angle);\n" +
+                    "  float y = dist * cos(angle) * 0.892;\n" +
+                    "  float p = dist * 5.5;\n" +
+                    "  float s = cos(p);\n" +
+                    "  float t = sin(p);\n" +
+                    "  vec4 pos;\n" +
+                    "  pos.x = t * x + s * y;\n" +
+                    "  pos.y = s * x - t * y;\n" +
+                    "  pos.z = ATTRIB_position.z;\n" +
+                    "  pos.w = 1.0;\n" +
+                    "  gl_Position = UNI_MVP * pos;\n" +
+                    "  gl_PointSize = ATTRIB_color.a * 10.0;\n" +
+                    "  varColor.rgb = ATTRIB_color.rgb;\n" +
+                    "  varColor.a = 1.0;\n" +
+                    "}\n";
+        sb.setShader(t);
+        sb.addInput(mParticlesMesh.getVertexAllocation(0).getType().getElement());
+        sb.addConstant(mPvStarAlloc.getType());
+        ProgramVertex pvs = sb.create();
+        pvs.bindConstants(mPvStarAlloc.getAllocation(), 0);
+        mUiScript.set_gPVStars(pvs);
+
+        // For Galaxy live wallpaper
+        mUiScript.set_gTSpace(loadTextureRGB(R.drawable.space));
+        mUiScript.set_gTLight1(loadTextureRGB(R.drawable.light1));
+        mUiScript.set_gTFlares(loadTextureARGB(R.drawable.flares));
+
+        mUiScript.set_gFontSans(mFontSans);
+    }
+}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/fill_test.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/fill_test.rs
new file mode 100644
index 0000000..23832d3
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/fill_test.rs
@@ -0,0 +1,137 @@
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.perftest)
+
+#include "rs_graphics.rsh"
+#include "subtest_def.rsh"
+
+rs_program_vertex gProgVertex;
+rs_program_fragment gProgFragmentTexture;
+rs_program_fragment gProgFragmentMultitex;
+
+rs_program_store gProgStoreBlendNone;
+rs_program_store gProgStoreBlendAlpha;
+
+rs_allocation gTexOpaque;
+rs_allocation gTexTorus;
+rs_allocation gTexTransparent;
+rs_allocation gTexChecker;
+
+rs_sampler gLinearClamp;
+rs_sampler gLinearWrap;
+
+typedef struct FillTestData_s {
+    int testId;
+    int blend;
+    int quadCount;
+} FillTestData;
+FillTestData *gData;
+
+static float gDt = 0.0f;
+
+void init() {
+}
+
+static int gRenderSurfaceW = 1280;
+static int gRenderSurfaceH = 720;
+
+static void bindProgramVertexOrtho() {
+    // Default vertex shader
+    rsgBindProgramVertex(gProgVertex);
+    // Setup the projection matrix
+    rs_matrix4x4 proj;
+    rsMatrixLoadOrtho(&proj, 0, gRenderSurfaceW, gRenderSurfaceH, 0, -500, 500);
+    rsgProgramVertexLoadProjectionMatrix(&proj);
+}
+
+static void displaySingletexFill(bool blend, int quadCount) {
+    bindProgramVertexOrtho();
+    rs_matrix4x4 matrix;
+    rsMatrixLoadIdentity(&matrix);
+    rsgProgramVertexLoadModelMatrix(&matrix);
+
+    // Fragment shader with texture
+    if (!blend) {
+        rsgBindProgramStore(gProgStoreBlendNone);
+    } else {
+        rsgBindProgramStore(gProgStoreBlendAlpha);
+    }
+    rsgBindProgramFragment(gProgFragmentTexture);
+    rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+    rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque);
+
+    for (int i = 0; i < quadCount; i ++) {
+        float startX = 5 * i, startY = 5 * i;
+        float width = gRenderSurfaceW - startX, height = gRenderSurfaceH - startY;
+        rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
+                             startX, startY + height, 0, 0, 1,
+                             startX + width, startY + height, 0, 1, 1,
+                             startX + width, startY, 0, 1, 0);
+    }
+}
+
+static void displayMultitextureSample(bool blend, int quadCount) {
+    bindProgramVertexOrtho();
+    rs_matrix4x4 matrix;
+    rsMatrixLoadIdentity(&matrix);
+    rsgProgramVertexLoadModelMatrix(&matrix);
+
+    // Fragment shader with texture
+    if (!blend) {
+        rsgBindProgramStore(gProgStoreBlendNone);
+    } else {
+        rsgBindProgramStore(gProgStoreBlendAlpha);
+    }
+    rsgBindProgramFragment(gProgFragmentMultitex);
+    rsgBindSampler(gProgFragmentMultitex, 0, gLinearClamp);
+    rsgBindSampler(gProgFragmentMultitex, 1, gLinearWrap);
+    rsgBindSampler(gProgFragmentMultitex, 2, gLinearClamp);
+    rsgBindTexture(gProgFragmentMultitex, 0, gTexChecker);
+    rsgBindTexture(gProgFragmentMultitex, 1, gTexTorus);
+    rsgBindTexture(gProgFragmentMultitex, 2, gTexTransparent);
+
+    for (int i = 0; i < quadCount; i ++) {
+        float startX = 10 * i, startY = 10 * i;
+        float width = gRenderSurfaceW - startX, height = gRenderSurfaceH - startY;
+        rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
+                             startX, startY + height, 0, 0, 1,
+                             startX + width, startY + height, 0, 1, 1,
+                             startX + width, startY, 0, 1, 0);
+    }
+}
+
+
+void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32_t y) {
+    TestData *testData = (TestData*)usrData;
+    gRenderSurfaceW = testData->renderSurfaceW;
+    gRenderSurfaceH = testData->renderSurfaceH;
+    gDt = testData->dt;
+
+    gData = (FillTestData*)v_in;
+
+    switch(gData->testId) {
+        case 0:
+            displayMultitextureSample(gData->blend == 1 ? true : false, gData->quadCount);
+            break;
+        case 1:
+            displaySingletexFill(gData->blend == 1 ? true : false, gData->quadCount);
+            break;
+        default:
+            rsDebug("Wrong test number", 0);
+            break;
+    }
+}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/mesh_test.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/mesh_test.rs
new file mode 100644
index 0000000..d7e4857
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/mesh_test.rs
@@ -0,0 +1,89 @@
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.perftest)
+
+#include "rs_graphics.rsh"
+#include "shader_def.rsh"
+#include "subtest_def.rsh"
+
+rs_program_vertex gProgVertex;
+rs_program_fragment gProgFragmentTexture;
+
+rs_program_store gProgStoreBlendNone;
+
+rs_allocation gTexOpaque;
+
+rs_mesh g10by10Mesh;
+rs_mesh g100by100Mesh;
+rs_mesh gWbyHMesh;
+
+rs_sampler gLinearClamp;
+static int gRenderSurfaceW;
+static int gRenderSurfaceH;
+
+static float gDt = 0;
+
+typedef struct MeshTestData_s {
+    int meshNum;
+} MeshTestData;
+MeshTestData *gData;
+
+void init() {
+}
+
+static void bindProgramVertexOrtho() {
+    // Default vertex shader
+    rsgBindProgramVertex(gProgVertex);
+    // Setup the projection matrix
+    rs_matrix4x4 proj;
+    rsMatrixLoadOrtho(&proj, 0, gRenderSurfaceW, gRenderSurfaceH, 0, -500, 500);
+    rsgProgramVertexLoadProjectionMatrix(&proj);
+}
+
+static void displayMeshSamples(int meshNum) {
+
+    bindProgramVertexOrtho();
+    rs_matrix4x4 matrix;
+    rsMatrixLoadTranslate(&matrix, gRenderSurfaceW/2, gRenderSurfaceH/2, 0);
+    rsgProgramVertexLoadModelMatrix(&matrix);
+
+    // Fragment shader with texture
+    rsgBindProgramStore(gProgStoreBlendNone);
+    rsgBindProgramFragment(gProgFragmentTexture);
+    rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+
+    rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque);
+
+    if (meshNum == 0) {
+        rsgDrawMesh(g10by10Mesh);
+    } else if (meshNum == 1) {
+        rsgDrawMesh(g100by100Mesh);
+    } else if (meshNum == 2) {
+        rsgDrawMesh(gWbyHMesh);
+    }
+}
+
+void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32_t y) {
+    TestData *testData = (TestData*)usrData;
+    gRenderSurfaceW = testData->renderSurfaceW;
+    gRenderSurfaceH = testData->renderSurfaceH;
+    gDt = testData->dt;
+
+    gData = (MeshTestData*)v_in;
+
+    displayMeshSamples(gData->meshNum);
+}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
index db97835..68f2814 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
@@ -1,4 +1,4 @@
-// Copyright (C) 2009 The Android Open Source Project
+// Copyright (C) 2010-2011 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -24,105 +24,33 @@
 const int RS_MSG_TEST_DONE = 100;
 const int RS_MSG_RESULTS_READY = 101;
 
-const int gMaxModes = 31;
-int gMaxLoops;
+static const int gMaxModes = 64;
+int gMaxLoops = 1;
+int gDisplayMode = 1;
 
-// Parameters for galaxy live wallpaper
-rs_allocation gTSpace;
-rs_allocation gTLight1;
-rs_allocation gTFlares;
-rs_mesh gParticlesMesh;
-
-rs_program_fragment gPFBackground;
-rs_program_fragment gPFStars;
-rs_program_vertex gPVStars;
-rs_program_vertex gPVBkProj;
-rs_program_store gPSLights;
-
-float gXOffset = 0.5f;
-
-#define ELLIPSE_RATIO 0.892f
-#define PI 3.1415f
-#define TWO_PI 6.283f
-#define ELLIPSE_TWIST 0.023333333f
-
-static float angle = 50.f;
-static int gOldWidth;
-static int gOldHeight;
-static int gWidth;
-static int gHeight;
-static float gSpeed[12000];
-static int gGalaxyRadius = 300;
-static rs_allocation gParticlesBuffer;
-
-typedef struct __attribute__((packed, aligned(4))) Particle {
-    uchar4 color;
-    float3 position;
-} Particle_t;
-Particle_t *Particles;
-
-typedef struct VpConsts {
-    rs_matrix4x4 Proj;
-    rs_matrix4x4 MVP;
-} VpConsts_t;
-VpConsts_t *vpConstants;
-// End of parameters for galaxy live wallpaper
-
-// Allocation to send test names back to java
-char *gStringBuffer = 0;
 // Allocation to write the results into
 static float gResultBuffer[gMaxModes];
 
-rs_program_vertex gProgVertex;
-rs_program_fragment gProgFragmentColor;
-rs_program_fragment gProgFragmentTexture;
-
-rs_program_store gProgStoreBlendNoneDepth;
-rs_program_store gProgStoreBlendNone;
-rs_program_store gProgStoreBlendAlpha;
-rs_program_store gProgStoreBlendAdd;
-
-rs_allocation gTexOpaque;
-rs_allocation gTexTorus;
-rs_allocation gTexTransparent;
-rs_allocation gTexChecker;
-rs_allocation gTexGlobe;
-
-typedef struct ListAllocs_s {
-    rs_allocation item;
-} ListAllocs;
-
-ListAllocs *gTexList100;
-ListAllocs *gSampleTextList100;
-ListAllocs *gListViewText;
-
-rs_mesh g10by10Mesh;
-rs_mesh g100by100Mesh;
-rs_mesh gWbyHMesh;
-rs_mesh gSingleMesh;
-
-rs_font gFontSans;
 rs_font gFontSerif;
-
-int gDisplayMode;
-
 rs_sampler gLinearClamp;
-rs_sampler gLinearWrap;
-rs_sampler gMipLinearWrap;
-rs_sampler gNearestClamp;
 
-rs_program_raster gCullBack;
-rs_program_raster gCullFront;
-rs_program_raster gCullNone;
-
-// Export these out to easily set the inputs to shader
-VertexShaderInputs *gVSInputs;
-
-rs_program_fragment gProgFragmentMultitex;
+rs_program_vertex gProgVertex;
+rs_program_fragment gProgFragmentTexture;
 
 rs_allocation gRenderBufferColor;
 rs_allocation gRenderBufferDepth;
 
+VertexShaderInputs *gVSInputs;
+
+typedef struct TestScripts_s {
+    rs_allocation testData;
+    rs_allocation testName;
+    rs_script testScript;
+} TestScripts;
+TestScripts *gTestScripts;
+
+bool gLoadComplete = false;
+
 static float gDt = 0;
 
 void init() {
@@ -131,158 +59,17 @@
 static int gRenderSurfaceW;
 static int gRenderSurfaceH;
 
-/**
-  * Methods to draw the galaxy live wall paper
-  */
-static float mapf(float minStart, float minStop, float maxStart, float maxStop, float value) {
-    return maxStart + (maxStart - maxStop) * ((value - minStart) / (minStop - minStart));
+static void fillSurfaceParams(TestData *testData) {
+    testData->renderSurfaceW = gRenderSurfaceW;
+    testData->renderSurfaceH = gRenderSurfaceH;
+    testData->dt = gDt;
 }
 
-/**
- * Helper function to generate the stars.
- */
-static float randomGauss() {
-    float x1;
-    float x2;
-    float w = 2.f;
-
-    while (w >= 1.0f) {
-        x1 = rsRand(2.0f) - 1.0f;
-        x2 = rsRand(2.0f) - 1.0f;
-        w = x1 * x1 + x2 * x2;
-    }
-
-    w = sqrt(-2.0f * log(w) / w);
-    return x1 * w;
-}
-
-/**
- * Generates the properties for a given star.
- */
-static void createParticle(Particle_t *part, int idx, float scale) {
-    float d = fabs(randomGauss()) * gGalaxyRadius * 0.5f + rsRand(64.0f);
-    float id = d / gGalaxyRadius;
-    float z = randomGauss() * 0.4f * (1.0f - id);
-    float p = -d * ELLIPSE_TWIST;
-
-    if (d < gGalaxyRadius * 0.33f) {
-        part->color.x = (uchar) (220 + id * 35);
-        part->color.y = 220;
-        part->color.z = 220;
-    } else {
-        part->color.x = 180;
-        part->color.y = 180;
-        part->color.z = (uchar) clamp(140.f + id * 115.f, 140.f, 255.f);
-    }
-    // Stash point size * 10 in Alpha
-    part->color.w = (uchar) (rsRand(1.2f, 2.1f) * 60);
-
-    if (d > gGalaxyRadius * 0.15f) {
-        z *= 0.6f * (1.0f - id);
-    } else {
-        z *= 0.72f;
-    }
-
-    // Map to the projection coordinates (viewport.x = -1.0 -> 1.0)
-    d = mapf(-4.0f, gGalaxyRadius + 4.0f, 0.0f, scale, d);
-
-    part->position.x = rsRand(TWO_PI);
-    part->position.y = d;
-    gSpeed[idx] = rsRand(0.0015f, 0.0025f) * (0.5f + (scale / d)) * 0.8f;
-
-    part->position.z = z / 5.0f;
-}
-
-/**
- * Initialize all the starts, called from Java
- */
-void initParticles() {
-    Particle_t *part = Particles;
-    float scale = gGalaxyRadius / (gWidth * 0.5f);
-    int count = rsAllocationGetDimX(gParticlesBuffer);
-    for (int i = 0; i < count; i ++) {
-        createParticle(part, i, scale);
-        part++;
-    }
-}
-
-static void drawSpace() {
-    rsgBindProgramFragment(gPFBackground);
-    rsgBindTexture(gPFBackground, 0, gTSpace);
-    rsgDrawQuadTexCoords(
-            0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-            gWidth, 0.0f, 0.0f, 2.0f, 1.0f,
-            gWidth, gHeight, 0.0f, 2.0f, 0.0f,
-            0.0f, gHeight, 0.0f, 0.0f, 0.0f);
-}
-
-static void drawLights() {
-    rsgBindProgramVertex(gPVBkProj);
-    rsgBindProgramFragment(gPFBackground);
-    rsgBindTexture(gPFBackground, 0, gTLight1);
-
-    float scale = 512.0f / gWidth;
-    float x = -scale - scale * 0.05f;
-    float y = -scale;
-
-    scale *= 2.0f;
-
-    rsgDrawQuad(x, y, 0.0f,
-             x + scale * 1.1f, y, 0.0f,
-             x + scale * 1.1f, y + scale, 0.0f,
-             x, y + scale, 0.0f);
-}
-
-static void drawParticles(float offset) {
-    float a = offset * angle;
-    float absoluteAngle = fabs(a);
-
-    rs_matrix4x4 matrix;
-    rsMatrixLoadTranslate(&matrix, 0.0f, 0.0f, 10.0f - 6.0f * absoluteAngle / 50.0f);
-    if (gHeight > gWidth) {
-        rsMatrixScale(&matrix, 6.6f, 6.0f, 1.0f);
-    } else {
-        rsMatrixScale(&matrix, 12.6f, 12.0f, 1.0f);
-    }
-    rsMatrixRotate(&matrix, absoluteAngle, 1.0f, 0.0f, 0.0f);
-    rsMatrixRotate(&matrix, a, 0.0f, 0.4f, 0.1f);
-    rsMatrixLoad(&vpConstants->MVP, &vpConstants->Proj);
-    rsMatrixMultiply(&vpConstants->MVP, &matrix);
-    rsgAllocationSyncAll(rsGetAllocation(vpConstants));
-
-    rsgBindProgramVertex(gPVStars);
-    rsgBindProgramFragment(gPFStars);
-    rsgBindProgramStore(gPSLights);
-    rsgBindTexture(gPFStars, 0, gTFlares);
-
-    Particle_t *vtx = Particles;
-    int count = rsAllocationGetDimX(gParticlesBuffer);
-    for (int i = 0; i < count; i++) {
-        vtx->position.x = vtx->position.x + gSpeed[i];
-        vtx++;
-    }
-
-    rsgDrawMesh(gParticlesMesh);
-}
-/* end of methods for drawing galaxy */
-
 static void setupOffscreenTarget() {
     rsgBindColorTarget(gRenderBufferColor, 0);
     rsgBindDepthTarget(gRenderBufferDepth);
 }
 
-rs_script gFontScript;
-rs_script gTorusScript;
-rs_allocation gDummyAlloc;
-
-static void displayFontSamples(int fillNum) {
-    TestData testData;
-    testData.renderSurfaceW = gRenderSurfaceW;
-    testData.renderSurfaceH = gRenderSurfaceH;
-    testData.user = fillNum;
-    rsForEach(gFontScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData));
-}
-
 static void bindProgramVertexOrtho() {
     // Default vertex shader
     rsgBindProgramVertex(gProgVertex);
@@ -292,302 +79,31 @@
     rsgProgramVertexLoadProjectionMatrix(&proj);
 }
 
-static void displaySingletexFill(bool blend, int quadCount) {
-    bindProgramVertexOrtho();
-    rs_matrix4x4 matrix;
-    rsMatrixLoadIdentity(&matrix);
-    rsgProgramVertexLoadModelMatrix(&matrix);
-
-    // Fragment shader with texture
-    if (!blend) {
-        rsgBindProgramStore(gProgStoreBlendNone);
-    } else {
-        rsgBindProgramStore(gProgStoreBlendAlpha);
-    }
-    rsgBindProgramFragment(gProgFragmentTexture);
-    rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
-    rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque);
-
-    for (int i = 0; i < quadCount; i ++) {
-        float startX = 5 * i, startY = 5 * i;
-        float width = gRenderSurfaceW - startX, height = gRenderSurfaceH - startY;
-        rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
-                             startX, startY + height, 0, 0, 1,
-                             startX + width, startY + height, 0, 1, 1,
-                             startX + width, startY, 0, 1, 0);
-    }
-}
-
-static void displayMeshSamples(int meshNum) {
-
-    bindProgramVertexOrtho();
-    rs_matrix4x4 matrix;
-    rsMatrixLoadTranslate(&matrix, gRenderSurfaceW/2, gRenderSurfaceH/2, 0);
-    rsgProgramVertexLoadModelMatrix(&matrix);
-
-    // Fragment shader with texture
-    rsgBindProgramStore(gProgStoreBlendNone);
-    rsgBindProgramFragment(gProgFragmentTexture);
-    rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
-
-    rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque);
-
-    if (meshNum == 0) {
-        rsgDrawMesh(g10by10Mesh);
-    } else if (meshNum == 1) {
-        rsgDrawMesh(g100by100Mesh);
-    } else if (meshNum == 2) {
-        rsgDrawMesh(gWbyHMesh);
-    }
-}
-
-// Display sample images in a mesh with different texture
-static void displayIcons(int meshMode) {
-    bindProgramVertexOrtho();
-
-    // Fragment shader with texture
-    rsgBindProgramStore(gProgStoreBlendAlpha);
-    rsgBindProgramFragment(gProgFragmentTexture);
-    rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
-    rsgBindTexture(gProgFragmentTexture, 0, gTexTorus);
-    rsgDrawQuadTexCoords(
-            0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
-            0.0f, gRenderSurfaceH, 0.0f, 0.0f, 1.0f,
-            gRenderSurfaceW, gRenderSurfaceH, 0.0f, 1.0f, 1.0f,
-            gRenderSurfaceW, 0.0f, 0.0f, 1.0f, 0.0f);
-
-    int meshCount = (int)pow(10.0f, (float)(meshMode + 1));
-
-    float wSize = gRenderSurfaceW/(float)meshCount;
-    float hSize = gRenderSurfaceH/(float)meshCount;
-    rs_matrix4x4 matrix;
-    rsMatrixLoadScale(&matrix, wSize, hSize, 1.0);
-
-    float yPos = 0;
-    float yPad = hSize / 2;
-    float xPad = wSize / 2;
-    for (int y = 0; y < meshCount; y++) {
-        yPos = y * hSize + yPad;
-        float xPos = 0;
-        for (int x = 0; x < meshCount; x++) {
-            xPos = x * wSize + xPad;
-            rs_matrix4x4 transMatrix;
-            rsMatrixLoadTranslate(&transMatrix, xPos, yPos, 0);
-            rsMatrixMultiply(&transMatrix, &matrix);
-            rsgProgramVertexLoadModelMatrix(&transMatrix);
-            int i = (x + y * meshCount) % 100;
-            rsgBindTexture(gProgFragmentTexture, 0, gTexList100[i].item);
-            rsgDrawMesh(gSingleMesh);
-        }
-    }
-}
-
-// Draw meshes in a single page with top left corner coordinates (xStart, yStart)
-static void drawMeshInPage(float xStart, float yStart, int wResolution, int hResolution) {
-    // Draw wResolution * hResolution meshes in one page
-    float wMargin = 100.0f;
-    float hMargin = 100.0f;
-    float xPad = 50.0f;
-    float yPad = 20.0f;
-    float size = 100.0f;  // size of images
-
-    // font info
-    rs_font font = gFontSans;
-    rsgBindFont(font);
-    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
-
-    // Measure text size
-    int left = 0, right = 0, top = 0, bottom = 0;
-    rsgMeasureText(gSampleTextList100[0].item, &left, &right, &top, &bottom);
-    float textHeight = (float)(top - bottom);
-    float textWidth = (float)(right - left);
-
-    rs_matrix4x4 matrix;
-    rsMatrixLoadScale(&matrix, size, size, 1.0);
-
-    for (int y = 0; y < hResolution; y++) {
-        float yPos = yStart + hMargin + y * size + y * yPad;
-        for (int x = 0; x < wResolution; x++) {
-            float xPos = xStart + wMargin + x * size + x * xPad;
-
-            rs_matrix4x4 transMatrix;
-            rsMatrixLoadTranslate(&transMatrix, xPos + size/2, yPos + size/2, 0);
-            rsMatrixMultiply(&transMatrix, &matrix);  // scale the mesh
-            rsgProgramVertexLoadModelMatrix(&transMatrix);
-
-            int i = (y * wResolution + x) % 100;
-            rsgBindTexture(gProgFragmentTexture, 0, gTexList100[i].item);
-            rsgDrawMesh(gSingleMesh);
-            rsgDrawText(gSampleTextList100[i].item, xPos, yPos + size + yPad/2 + textHeight);
-        }
-    }
-}
-
-// Display both images and text as shown in launcher and homepage
-// meshMode will decide how many pages we draw
-// meshMode = 0: draw 3 pages of meshes
-// meshMode = 1: draw 5 pages of meshes
-static void displayImageWithText(int wResolution, int hResolution, int meshMode) {
-    bindProgramVertexOrtho();
-
-    // Fragment shader with texture
-    rsgBindProgramStore(gProgStoreBlendAlpha);
-    rsgBindProgramFragment(gProgFragmentTexture);
-    rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
-
-    drawMeshInPage(0, 0, wResolution, hResolution);
-    drawMeshInPage(-1.0f*gRenderSurfaceW, 0, wResolution, hResolution);
-    drawMeshInPage(1.0f*gRenderSurfaceW, 0, wResolution, hResolution);
-    if (meshMode == 1) {
-        // draw another two pages of meshes
-        drawMeshInPage(-2.0f*gRenderSurfaceW, 0, wResolution, hResolution);
-        drawMeshInPage(2.0f*gRenderSurfaceW, 0, wResolution, hResolution);
-    }
-}
-
-// Display a list of text as the list view
-static void displayListView() {
-    // set text color
-    rsgFontColor(0.9f, 0.9f, 0.9f, 1.0f);
-    rsgBindFont(gFontSans);
-
-    // get the size of the list
-    rs_allocation textAlloc;
-    textAlloc = rsGetAllocation(gListViewText);
-    int allocSize = rsAllocationGetDimX(textAlloc);
-
-    int listItemHeight = 80;
-    int yOffset = listItemHeight;
-
-    // set the color for the list divider
-    rsgBindProgramFragment(gProgFragmentColor);
-    rsgProgramFragmentConstantColor(gProgFragmentColor, 1.0, 1.0, 1.0, 1);
-
-    // draw the list with divider
-    for (int i = 0; i < allocSize; i++) {
-        if (yOffset - listItemHeight > gRenderSurfaceH) {
-            break;
-        }
-        rsgDrawRect(0, yOffset - 1, gRenderSurfaceW, yOffset, 0);
-        rsgDrawText(gListViewText[i].item, 20, yOffset - 10);
-        yOffset += listItemHeight;
-    }
-}
-
-static void drawGalaxy() {
-    rsgClearColor(0.f, 0.f, 0.f, 1.f);
-    gParticlesBuffer = rsGetAllocation(Particles);
-    rsgBindProgramFragment(gPFBackground);
-
-    gWidth = rsgGetWidth();
-    gHeight = rsgGetHeight();
-    if ((gWidth != gOldWidth) || (gHeight != gOldHeight)) {
-        initParticles();
-        gOldWidth = gWidth;
-        gOldHeight = gHeight;
-    }
-
-    float offset = mix(-1.0f, 1.0f, gXOffset);
-    drawSpace();
-    drawParticles(offset);
-    drawLights();
-}
-
-// Display images and text with live wallpaper in the background
-static void displayLiveWallPaper(int wResolution, int hResolution) {
-    bindProgramVertexOrtho();
-
-    drawGalaxy();
-
-    rsgBindProgramVertex(gProgVertex);
-    rsgBindProgramStore(gProgStoreBlendAlpha);
-    rsgBindProgramFragment(gProgFragmentTexture);
-    rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
-
-    drawMeshInPage(0, 0, wResolution, hResolution);
-    drawMeshInPage(-1.0f*gRenderSurfaceW, 0, wResolution, hResolution);
-    drawMeshInPage(1.0f*gRenderSurfaceW, 0, wResolution, hResolution);
-    drawMeshInPage(-2.0f*gRenderSurfaceW, 0, wResolution, hResolution);
-    drawMeshInPage(2.0f*gRenderSurfaceW, 0, wResolution, hResolution);
-}
-
-// Quick hack to get some geometry numbers
-static void displaySimpleGeoSamples(bool useTexture, int numMeshes) {
+static void runSubTest(int index) {
     TestData testData;
-    testData.renderSurfaceW = gRenderSurfaceW;
-    testData.renderSurfaceH = gRenderSurfaceH;
-    testData.dt = gDt;
-    testData.user = 0;
-    testData.user1 = useTexture ? 1 : 0;
-    testData.user2 = numMeshes;
-    rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData));
+    fillSurfaceParams(&testData);
+
+    rs_allocation null_alloc;
+    rsForEach(gTestScripts[index].testScript,
+              gTestScripts[index].testData,
+              null_alloc,
+              &testData,
+              sizeof(testData));
 }
 
-static void displayCustomShaderSamples(int numMeshes) {
-    TestData testData;
-    testData.renderSurfaceW = gRenderSurfaceW;
-    testData.renderSurfaceH = gRenderSurfaceH;
-    testData.dt = gDt;
-    testData.user = 1;
-    testData.user1 = numMeshes;
-    rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData));
-}
-
-static void displayPixelLightSamples(int numMeshes, bool heavyVertex) {
-    TestData testData;
-    testData.renderSurfaceW = gRenderSurfaceW;
-    testData.renderSurfaceH = gRenderSurfaceH;
-    testData.dt = gDt;
-    testData.user = 2;
-    testData.user1 = numMeshes;
-    testData.user2 = heavyVertex ? 1 : 0;
-    rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData));
-}
-
-static void displayMultitextureSample(bool blend, int quadCount) {
-    bindProgramVertexOrtho();
-    rs_matrix4x4 matrix;
-    rsMatrixLoadIdentity(&matrix);
-    rsgProgramVertexLoadModelMatrix(&matrix);
-
-    // Fragment shader with texture
-    if (!blend) {
-        rsgBindProgramStore(gProgStoreBlendNone);
-    } else {
-        rsgBindProgramStore(gProgStoreBlendAlpha);
-    }
-    rsgBindProgramFragment(gProgFragmentMultitex);
-    rsgBindSampler(gProgFragmentMultitex, 0, gLinearClamp);
-    rsgBindSampler(gProgFragmentMultitex, 1, gLinearWrap);
-    rsgBindSampler(gProgFragmentMultitex, 2, gLinearClamp);
-    rsgBindTexture(gProgFragmentMultitex, 0, gTexChecker);
-    rsgBindTexture(gProgFragmentMultitex, 1, gTexTorus);
-    rsgBindTexture(gProgFragmentMultitex, 2, gTexTransparent);
-
-    for (int i = 0; i < quadCount; i ++) {
-        float startX = 10 * i, startY = 10 * i;
-        float width = gRenderSurfaceW - startX, height = gRenderSurfaceH - startY;
-        rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
-                             startX, startY + height, 0, 0, 1,
-                             startX + width, startY + height, 0, 1, 1,
-                             startX + width, startY, 0, 1, 0);
-    }
-}
 
 static bool checkInit() {
 
-    static int countdown = 5;
+    static int countdown = 3;
 
     // Perform all the uploads so we only measure rendered time
     if(countdown > 1) {
-        displayFontSamples(5);
-        displaySingletexFill(true, 3);
-        displayMeshSamples(0);
-        displayMeshSamples(1);
-        displayMeshSamples(2);
-        displayMultitextureSample(true, 5);
-        displayPixelLightSamples(1, false);
-        displayPixelLightSamples(1, true);
+        int testCount = rsAllocationGetDimX(rsGetAllocation(gTestScripts));
+        for(int i = 0; i < testCount; i ++) {
+            rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f);
+            runSubTest(i);
+            rsgFinish();
+        }
         countdown --;
         rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f);
 
@@ -606,43 +122,10 @@
 }
 
 static int benchMode = 0;
+static int benchSubMode = 0;
 static int runningLoops = 0;
 static bool sendMsgFlag = false;
 
-static const char *testNames[] = {
-    "Fill screen with text 1 time",
-    "Fill screen with text 3 times",
-    "Fill screen with text 5 times",
-    "Geo test 25.6k flat color",
-    "Geo test 51.2k flat color",
-    "Geo test 204.8k small tries flat color",
-    "Geo test 25.6k single texture",
-    "Geo test 51.2k single texture",
-    "Geo test 204.8k small tries single texture",
-    "Full screen mesh 10 by 10",
-    "Full screen mesh 100 by 100",
-    "Full screen mesh W / 4 by H / 4",
-    "Geo test 25.6k geo heavy vertex",
-    "Geo test 51.2k geo heavy vertex",
-    "Geo test 204.8k geo raster load heavy vertex",
-    "Fill screen 10x singletexture",
-    "Fill screen 10x 3tex multitexture",
-    "Fill screen 10x blended singletexture",
-    "Fill screen 10x blended 3tex multitexture",
-    "Geo test 25.6k heavy fragment",
-    "Geo test 51.2k heavy fragment",
-    "Geo test 204.8k small tries heavy fragment",
-    "Geo test 25.6k heavy fragment heavy vertex",
-    "Geo test 51.2k heavy fragment heavy vertex",
-    "Geo test 204.8k small tries heavy fragment heavy vertex",
-    "UI test with icon display 10 by 10",
-    "UI test with icon display 100 by 100",
-    "UI test with image and text display 3 pages",
-    "UI test with image and text display 5 pages",
-    "UI test with list view",
-    "UI test with live wallpaper",
-};
-
 static bool gIsDebugMode = false;
 void setDebugMode(int testNumber) {
     gIsDebugMode = true;
@@ -656,118 +139,6 @@
     runningLoops = 0;
 }
 
-
-void getTestName(int testIndex) {
-    int bufferLen = rsAllocationGetDimX(rsGetAllocation(gStringBuffer));
-    if (testIndex >= gMaxModes) {
-        return;
-    }
-    uint charIndex = 0;
-    while (testNames[testIndex][charIndex] != '\0' && charIndex < bufferLen) {
-        gStringBuffer[charIndex] = testNames[testIndex][charIndex];
-        charIndex ++;
-    }
-    gStringBuffer[charIndex] = '\0';
-}
-
-static void runTest(int index) {
-    switch (index) {
-    case 0:
-        displayFontSamples(1);
-        break;
-    case 1:
-        displayFontSamples(3);
-        break;
-    case 2:
-        displayFontSamples(5);
-        break;
-    case 3:
-        displaySimpleGeoSamples(false, 1);
-        break;
-    case 4:
-        displaySimpleGeoSamples(false, 2);
-        break;
-    case 5:
-        displaySimpleGeoSamples(false, 8);
-        break;
-    case 6:
-        displaySimpleGeoSamples(true, 1);
-        break;
-    case 7:
-        displaySimpleGeoSamples(true, 2);
-        break;
-    case 8:
-        displaySimpleGeoSamples(true, 8);
-        break;
-    case 9:
-        displayMeshSamples(0);
-        break;
-    case 10:
-        displayMeshSamples(1);
-        break;
-    case 11:
-        displayMeshSamples(2);
-        break;
-    case 12:
-        displayCustomShaderSamples(1);
-        break;
-    case 13:
-        displayCustomShaderSamples(2);
-        break;
-    case 14:
-        displayCustomShaderSamples(10);
-        break;
-    case 15:
-        displaySingletexFill(false, 10);
-        break;
-    case 16:
-        displayMultitextureSample(false, 10);
-        break;
-    case 17:
-        displaySingletexFill(true, 10);
-        break;
-    case 18:
-        displayMultitextureSample(true, 10);
-        break;
-    case 19:
-        displayPixelLightSamples(1, false);
-        break;
-    case 20:
-        displayPixelLightSamples(2, false);
-        break;
-    case 21:
-        displayPixelLightSamples(8, false);
-        break;
-    case 22:
-        displayPixelLightSamples(1, true);
-        break;
-    case 23:
-        displayPixelLightSamples(2, true);
-        break;
-    case 24:
-        displayPixelLightSamples(8, true);
-        break;
-    case 25:
-        displayIcons(0);
-        break;
-    case 26:
-        displayIcons(1);
-        break;
-    case 27:
-        displayImageWithText(7, 5, 0);
-        break;
-    case 28:
-        displayImageWithText(7, 5, 1);
-        break;
-    case 29:
-        displayListView();
-        break;
-    case 30:
-        displayLiveWallPaper(7, 5);
-        break;
-    }
-}
-
 static void drawOffscreenResult(int posX, int posY, int width, int height) {
     bindProgramVertexOrtho();
 
@@ -803,7 +174,7 @@
         rsgClearColor(0.1f, 0.1f, 0.1f, 1.0f);
         rsgClearDepth(1.0f);
 
-        runTest(benchMode);
+        runSubTest(benchMode);
         rsgClearAllRenderTargets();
         gRenderSurfaceW = rsgGetWidth();
         gRenderSurfaceH = rsgGetHeight();
@@ -816,25 +187,25 @@
 
     int64_t end = rsUptimeMillis();
     float fps = (float)(frameCount) / ((float)(end - start)*0.001f);
-    rsDebug(testNames[benchMode], fps);
+    rsDebug("Finishes test ", fps);
+
     gResultBuffer[benchMode] = fps;
     drawOffscreenResult(0, 0,
                         gRenderSurfaceW / 2,
                         gRenderSurfaceH / 2);
-    const char* text = testNames[benchMode];
     int left = 0, right = 0, top = 0, bottom = 0;
     uint width = rsgGetWidth();
     uint height = rsgGetHeight();
     rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f);
     rsgBindFont(gFontSerif);
-    rsgMeasureText(text, &left, &right, &top, &bottom);
+    rsgMeasureText(gTestScripts[benchMode].testName, &left, &right, &top, &bottom);
     rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
-    rsgDrawText(text, 2 -left, height - 2 + bottom);
+    rsgDrawText(gTestScripts[benchMode].testName, 2 -left, height - 2 + bottom);
 
     benchMode ++;
-
-    if (benchMode == gMaxModes) {
-        rsSendToClientBlocking(RS_MSG_RESULTS_READY, gResultBuffer, gMaxModes*sizeof(float));
+    int testCount = rsAllocationGetDimX(rsGetAllocation(gTestScripts));
+    if (benchMode == testCount) {
+        rsSendToClientBlocking(RS_MSG_RESULTS_READY, gResultBuffer, testCount*sizeof(float));
         benchMode = 0;
         runningLoops++;
         if ((gMaxLoops > 0) && (runningLoops > gMaxLoops) && !sendMsgFlag) {
@@ -844,14 +215,11 @@
             sendMsgFlag = true;
         }
     }
-
 }
 
 static void debug() {
     gDt = rsGetDt();
-
-    rsgFinish();
-    runTest(benchMode);
+    runSubTest(benchMode);
 }
 
 int root(void) {
@@ -859,6 +227,14 @@
     gRenderSurfaceH = rsgGetHeight();
     rsgClearColor(0.2f, 0.2f, 0.2f, 1.0f);
     rsgClearDepth(1.0f);
+
+    if (!gLoadComplete) {
+        rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f);
+        rsgBindFont(gFontSerif);
+        rsgDrawText("Loading", 50, 50);
+        return 0;
+    }
+
     if(!checkInit()) {
         return 1;
     }
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/subtest_def.rsh b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/subtest_def.rsh
index b635373b..43658b1 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/subtest_def.rsh
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/subtest_def.rsh
@@ -20,9 +20,5 @@
     int renderSurfaceW;
     int renderSurfaceH;
     float dt;
-    int user;
-    int user1;
-    int user2;
-    int user3;
 } TestData;
 
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/text_test.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/text_test.rs
index 0df6b35..7f10019 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/text_test.rs
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/text_test.rs
@@ -22,6 +22,11 @@
 rs_font gFontSans;
 rs_font gFontSerif;
 
+typedef struct TextTestData_s {
+    int fillNum;
+} TextTestData;
+TextTestData *gData;
+
 void init() {
 }
 
@@ -78,5 +83,8 @@
     TestData *testData = (TestData*)usrData;
     gRenderSurfaceW = testData->renderSurfaceW;
     gRenderSurfaceH = testData->renderSurfaceH;
-    displayFontSamples(testData->user);
+
+    gData = (TextTestData*)v_in;
+
+    displayFontSamples(gData->fillNum);
 }
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/torus_test.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/torus_test.rs
index 26d5680..853a05d 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/torus_test.rs
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/torus_test.rs
@@ -47,6 +47,13 @@
 rs_program_vertex gProgVertexPixelLightMove;
 rs_program_fragment gProgFragmentPixelLight;
 
+typedef struct TorusTestData_s {
+    int testId;
+    int user1;
+    int user2;
+} TorusTestData;
+TorusTestData *gData;
+
 static float gDt = 0.0f;
 
 static int gRenderSurfaceW;
@@ -269,15 +276,20 @@
     gRenderSurfaceH = testData->renderSurfaceH;
     gDt = testData->dt;
 
-    switch(testData->user) {
+    gData = (TorusTestData*)v_in;
+
+    switch(gData->testId) {
         case 0:
-            displaySimpleGeoSamples(testData->user1 == 1 ? true : false, testData->user2);
+            displaySimpleGeoSamples(gData->user1 == 1 ? true : false, gData->user2);
             break;
         case 1:
-            displayCustomShaderSamples(testData->user1);
+            displayCustomShaderSamples(gData->user1);
             break;
         case 2:
-            displayPixelLightSamples(testData->user1, testData->user2 == 1 ? true : false);
+            displayPixelLightSamples(gData->user1, gData->user2 == 1 ? true : false);
+            break;
+        default:
+            rsDebug("Wrong test number", gData->testId);
             break;
     }
 }
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/ui_test.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/ui_test.rs
new file mode 100644
index 0000000..5089092
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/ui_test.rs
@@ -0,0 +1,444 @@
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.perftest)
+
+#include "rs_graphics.rsh"
+#include "shader_def.rsh"
+#include "subtest_def.rsh"
+
+// Parameters for galaxy live wallpaper
+rs_allocation gTSpace;
+rs_allocation gTLight1;
+rs_allocation gTFlares;
+rs_mesh gParticlesMesh;
+
+rs_program_fragment gPFBackground;
+rs_program_fragment gPFStars;
+rs_program_vertex gPVStars;
+rs_program_vertex gPVBkProj;
+rs_program_store gPSLights;
+
+float gXOffset = 0.5f;
+
+#define ELLIPSE_RATIO 0.892f
+#define PI 3.1415f
+#define TWO_PI 6.283f
+#define ELLIPSE_TWIST 0.023333333f
+
+static float angle = 50.f;
+static int gOldWidth;
+static int gOldHeight;
+static int gWidth;
+static int gHeight;
+static float gSpeed[12000];
+static int gGalaxyRadius = 300;
+static rs_allocation gParticlesBuffer;
+
+typedef struct __attribute__((packed, aligned(4))) Particle {
+    uchar4 color;
+    float3 position;
+} Particle_t;
+Particle_t *Particles;
+
+typedef struct VpConsts {
+    rs_matrix4x4 Proj;
+    rs_matrix4x4 MVP;
+} VpConsts_t;
+VpConsts_t *vpConstants;
+// End of parameters for galaxy live wallpaper
+
+rs_program_vertex gProgVertex;
+rs_program_fragment gProgFragmentColor;
+rs_program_fragment gProgFragmentTexture;
+
+rs_program_store gProgStoreBlendAlpha;
+
+rs_allocation gTexOpaque;
+rs_allocation gTexTorus;
+rs_allocation gTexGlobe;
+
+typedef struct ListAllocs_s {
+    rs_allocation item;
+} ListAllocs;
+
+ListAllocs *gTexList100;
+ListAllocs *gSampleTextList100;
+ListAllocs *gListViewText;
+
+rs_mesh gSingleMesh;
+
+rs_font gFontSans;
+
+rs_sampler gLinearClamp;
+
+typedef struct UiTestData_s {
+    int testId;
+    int user1;
+    int user2;
+    int user3;
+} UiTestData;
+UiTestData *gData;
+
+static float gDt = 0;
+
+
+void init() {
+}
+
+static int gRenderSurfaceW;
+static int gRenderSurfaceH;
+
+static void bindProgramVertexOrtho() {
+    // Default vertex shader
+    rsgBindProgramVertex(gProgVertex);
+    // Setup the projection matrix
+    rs_matrix4x4 proj;
+    rsMatrixLoadOrtho(&proj, 0, gRenderSurfaceW, gRenderSurfaceH, 0, -500, 500);
+    rsgProgramVertexLoadProjectionMatrix(&proj);
+}
+
+/**
+  * Methods to draw the galaxy live wall paper
+  */
+static float mapf(float minStart, float minStop, float maxStart, float maxStop, float value) {
+    return maxStart + (maxStart - maxStop) * ((value - minStart) / (minStop - minStart));
+}
+
+/**
+ * Helper function to generate the stars.
+ */
+static float randomGauss() {
+    float x1;
+    float x2;
+    float w = 2.f;
+
+    while (w >= 1.0f) {
+        x1 = rsRand(2.0f) - 1.0f;
+        x2 = rsRand(2.0f) - 1.0f;
+        w = x1 * x1 + x2 * x2;
+    }
+
+    w = sqrt(-2.0f * log(w) / w);
+    return x1 * w;
+}
+
+/**
+ * Generates the properties for a given star.
+ */
+static void createParticle(Particle_t *part, int idx, float scale) {
+    float d = fabs(randomGauss()) * gGalaxyRadius * 0.5f + rsRand(64.0f);
+    float id = d / gGalaxyRadius;
+    float z = randomGauss() * 0.4f * (1.0f - id);
+    float p = -d * ELLIPSE_TWIST;
+
+    if (d < gGalaxyRadius * 0.33f) {
+        part->color.x = (uchar) (220 + id * 35);
+        part->color.y = 220;
+        part->color.z = 220;
+    } else {
+        part->color.x = 180;
+        part->color.y = 180;
+        part->color.z = (uchar) clamp(140.f + id * 115.f, 140.f, 255.f);
+    }
+    // Stash point size * 10 in Alpha
+    part->color.w = (uchar) (rsRand(1.2f, 2.1f) * 60);
+
+    if (d > gGalaxyRadius * 0.15f) {
+        z *= 0.6f * (1.0f - id);
+    } else {
+        z *= 0.72f;
+    }
+
+    // Map to the projection coordinates (viewport.x = -1.0 -> 1.0)
+    d = mapf(-4.0f, gGalaxyRadius + 4.0f, 0.0f, scale, d);
+
+    part->position.x = rsRand(TWO_PI);
+    part->position.y = d;
+    gSpeed[idx] = rsRand(0.0015f, 0.0025f) * (0.5f + (scale / d)) * 0.8f;
+
+    part->position.z = z / 5.0f;
+}
+
+/**
+ * Initialize all the starts, called from Java
+ */
+void initParticles() {
+    Particle_t *part = Particles;
+    float scale = gGalaxyRadius / (gWidth * 0.5f);
+    int count = rsAllocationGetDimX(gParticlesBuffer);
+    for (int i = 0; i < count; i ++) {
+        createParticle(part, i, scale);
+        part++;
+    }
+}
+
+static void drawSpace() {
+    rsgBindProgramFragment(gPFBackground);
+    rsgBindTexture(gPFBackground, 0, gTSpace);
+    rsgDrawQuadTexCoords(
+            0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
+            gWidth, 0.0f, 0.0f, 2.0f, 1.0f,
+            gWidth, gHeight, 0.0f, 2.0f, 0.0f,
+            0.0f, gHeight, 0.0f, 0.0f, 0.0f);
+}
+
+static void drawLights() {
+    rsgBindProgramVertex(gPVBkProj);
+    rsgBindProgramFragment(gPFBackground);
+    rsgBindTexture(gPFBackground, 0, gTLight1);
+
+    float scale = 512.0f / gWidth;
+    float x = -scale - scale * 0.05f;
+    float y = -scale;
+
+    scale *= 2.0f;
+
+    rsgDrawQuad(x, y, 0.0f,
+             x + scale * 1.1f, y, 0.0f,
+             x + scale * 1.1f, y + scale, 0.0f,
+             x, y + scale, 0.0f);
+}
+
+static void drawParticles(float offset) {
+    float a = offset * angle;
+    float absoluteAngle = fabs(a);
+
+    rs_matrix4x4 matrix;
+    rsMatrixLoadTranslate(&matrix, 0.0f, 0.0f, 10.0f - 6.0f * absoluteAngle / 50.0f);
+    if (gHeight > gWidth) {
+        rsMatrixScale(&matrix, 6.6f, 6.0f, 1.0f);
+    } else {
+        rsMatrixScale(&matrix, 12.6f, 12.0f, 1.0f);
+    }
+    rsMatrixRotate(&matrix, absoluteAngle, 1.0f, 0.0f, 0.0f);
+    rsMatrixRotate(&matrix, a, 0.0f, 0.4f, 0.1f);
+    rsMatrixLoad(&vpConstants->MVP, &vpConstants->Proj);
+    rsMatrixMultiply(&vpConstants->MVP, &matrix);
+    rsgAllocationSyncAll(rsGetAllocation(vpConstants));
+
+    rsgBindProgramVertex(gPVStars);
+    rsgBindProgramFragment(gPFStars);
+    rsgBindProgramStore(gPSLights);
+    rsgBindTexture(gPFStars, 0, gTFlares);
+
+    Particle_t *vtx = Particles;
+    int count = rsAllocationGetDimX(gParticlesBuffer);
+    for (int i = 0; i < count; i++) {
+        vtx->position.x = vtx->position.x + gSpeed[i];
+        vtx++;
+    }
+
+    rsgDrawMesh(gParticlesMesh);
+}
+/* end of methods for drawing galaxy */
+
+// Display sample images in a mesh with different texture
+static void displayIcons(int meshMode) {
+    bindProgramVertexOrtho();
+
+    // Fragment shader with texture
+    rsgBindProgramStore(gProgStoreBlendAlpha);
+    rsgBindProgramFragment(gProgFragmentTexture);
+    rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+    rsgBindTexture(gProgFragmentTexture, 0, gTexTorus);
+    rsgDrawQuadTexCoords(
+            0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+            0.0f, gRenderSurfaceH, 0.0f, 0.0f, 1.0f,
+            gRenderSurfaceW, gRenderSurfaceH, 0.0f, 1.0f, 1.0f,
+            gRenderSurfaceW, 0.0f, 0.0f, 1.0f, 0.0f);
+
+    int meshCount = (int)pow(10.0f, (float)(meshMode + 1));
+
+    float wSize = gRenderSurfaceW/(float)meshCount;
+    float hSize = gRenderSurfaceH/(float)meshCount;
+    rs_matrix4x4 matrix;
+    rsMatrixLoadScale(&matrix, wSize, hSize, 1.0);
+
+    float yPos = 0;
+    float yPad = hSize / 2;
+    float xPad = wSize / 2;
+    for (int y = 0; y < meshCount; y++) {
+        yPos = y * hSize + yPad;
+        float xPos = 0;
+        for (int x = 0; x < meshCount; x++) {
+            xPos = x * wSize + xPad;
+            rs_matrix4x4 transMatrix;
+            rsMatrixLoadTranslate(&transMatrix, xPos, yPos, 0);
+            rsMatrixMultiply(&transMatrix, &matrix);
+            rsgProgramVertexLoadModelMatrix(&transMatrix);
+            int i = (x + y * meshCount) % 100;
+            rsgBindTexture(gProgFragmentTexture, 0, gTexList100[i].item);
+            rsgDrawMesh(gSingleMesh);
+        }
+    }
+}
+
+// Draw meshes in a single page with top left corner coordinates (xStart, yStart)
+static void drawMeshInPage(float xStart, float yStart, int wResolution, int hResolution) {
+    // Draw wResolution * hResolution meshes in one page
+    float wMargin = 100.0f;
+    float hMargin = 100.0f;
+    float xPad = 50.0f;
+    float yPad = 20.0f;
+    float size = 100.0f;  // size of images
+
+    // font info
+    rs_font font = gFontSans;
+    rsgBindFont(font);
+    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
+
+    // Measure text size
+    int left = 0, right = 0, top = 0, bottom = 0;
+    rsgMeasureText(gSampleTextList100[0].item, &left, &right, &top, &bottom);
+    float textHeight = (float)(top - bottom);
+    float textWidth = (float)(right - left);
+
+    rs_matrix4x4 matrix;
+    rsMatrixLoadScale(&matrix, size, size, 1.0);
+
+    for (int y = 0; y < hResolution; y++) {
+        float yPos = yStart + hMargin + y * size + y * yPad;
+        for (int x = 0; x < wResolution; x++) {
+            float xPos = xStart + wMargin + x * size + x * xPad;
+
+            rs_matrix4x4 transMatrix;
+            rsMatrixLoadTranslate(&transMatrix, xPos + size/2, yPos + size/2, 0);
+            rsMatrixMultiply(&transMatrix, &matrix);  // scale the mesh
+            rsgProgramVertexLoadModelMatrix(&transMatrix);
+
+            int i = (y * wResolution + x) % 100;
+            rsgBindTexture(gProgFragmentTexture, 0, gTexList100[i].item);
+            rsgDrawMesh(gSingleMesh);
+            rsgDrawText(gSampleTextList100[i].item, xPos, yPos + size + yPad/2 + textHeight);
+        }
+    }
+}
+
+// Display both images and text as shown in launcher and homepage
+// meshMode will decide how many pages we draw
+// meshMode = 0: draw 3 pages of meshes
+// meshMode = 1: draw 5 pages of meshes
+static void displayImageWithText(int wResolution, int hResolution, int meshMode) {
+    bindProgramVertexOrtho();
+
+    // Fragment shader with texture
+    rsgBindProgramStore(gProgStoreBlendAlpha);
+    rsgBindProgramFragment(gProgFragmentTexture);
+    rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+
+    drawMeshInPage(0, 0, wResolution, hResolution);
+    drawMeshInPage(-1.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+    drawMeshInPage(1.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+    if (meshMode == 1) {
+        // draw another two pages of meshes
+        drawMeshInPage(-2.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+        drawMeshInPage(2.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+    }
+}
+
+// Display a list of text as the list view
+static void displayListView() {
+    // set text color
+    rsgFontColor(0.9f, 0.9f, 0.9f, 1.0f);
+    rsgBindFont(gFontSans);
+
+    // get the size of the list
+    rs_allocation textAlloc;
+    textAlloc = rsGetAllocation(gListViewText);
+    int allocSize = rsAllocationGetDimX(textAlloc);
+
+    int listItemHeight = 80;
+    int yOffset = listItemHeight;
+
+    // set the color for the list divider
+    rsgBindProgramFragment(gProgFragmentColor);
+    rsgProgramFragmentConstantColor(gProgFragmentColor, 1.0, 1.0, 1.0, 1);
+
+    // draw the list with divider
+    for (int i = 0; i < allocSize; i++) {
+        if (yOffset - listItemHeight > gRenderSurfaceH) {
+            break;
+        }
+        rsgDrawRect(0, yOffset - 1, gRenderSurfaceW, yOffset, 0);
+        rsgDrawText(gListViewText[i].item, 20, yOffset - 10);
+        yOffset += listItemHeight;
+    }
+}
+
+static void drawGalaxy() {
+    rsgClearColor(0.f, 0.f, 0.f, 1.f);
+    gParticlesBuffer = rsGetAllocation(Particles);
+    rsgBindProgramFragment(gPFBackground);
+
+    gWidth = rsgGetWidth();
+    gHeight = rsgGetHeight();
+    if ((gWidth != gOldWidth) || (gHeight != gOldHeight)) {
+        initParticles();
+        gOldWidth = gWidth;
+        gOldHeight = gHeight;
+    }
+
+    float offset = mix(-1.0f, 1.0f, gXOffset);
+    drawSpace();
+    drawParticles(offset);
+    drawLights();
+}
+
+// Display images and text with live wallpaper in the background
+static void displayLiveWallPaper(int wResolution, int hResolution) {
+    bindProgramVertexOrtho();
+
+    drawGalaxy();
+
+    rsgBindProgramVertex(gProgVertex);
+    rsgBindProgramStore(gProgStoreBlendAlpha);
+    rsgBindProgramFragment(gProgFragmentTexture);
+    rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+
+    drawMeshInPage(0, 0, wResolution, hResolution);
+    drawMeshInPage(-1.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+    drawMeshInPage(1.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+    drawMeshInPage(-2.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+    drawMeshInPage(2.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+}
+
+void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32_t y) {
+    TestData *testData = (TestData*)usrData;
+    gRenderSurfaceW = testData->renderSurfaceW;
+    gRenderSurfaceH = testData->renderSurfaceH;
+    gDt = testData->dt;
+
+    gData = (UiTestData*)v_in;
+
+    switch(gData->testId) {
+        case 0:
+            displayIcons(gData->user1);
+            break;
+        case 1:
+            displayImageWithText(gData->user1, gData->user2, gData->user3);
+            break;
+        case 2:
+            displayListView();
+            break;
+        case 3:
+            displayLiveWallPaper(gData->user1, gData->user2);
+            break;
+        default:
+            rsDebug("Wrong test number", 0);
+            break;
+    }
+}