Merge "Add support for non-malloc backed textures."
diff --git a/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
index 09654ab..5de09f7 100644
--- a/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
+++ b/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
@@ -362,7 +362,7 @@
     }
 
     private void createScript() {
-        mRS = RenderScript.create();
+        mRS = RenderScript.create(this);
         mRS.setMessageHandler(new FilterCallback());
 
         mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn,
diff --git a/java/Samples/AndroidManifest.xml b/java/Samples/AndroidManifest.xml
index be191f2..6f35e2a 100644
--- a/java/Samples/AndroidManifest.xml
+++ b/java/Samples/AndroidManifest.xml
@@ -20,5 +20,14 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+
+        <activity android:name="RsBench"
+                  android:label="RsBenchmark"                  
+                  android:theme="@android:style/Theme.Black.NoTitleBar">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
     </application>
 </manifest>
diff --git a/java/Samples/res/raw/multitexf.glsl b/java/Samples/res/raw/multitexf.glsl
index 351ff9b..e492a47 100644
--- a/java/Samples/res/raw/multitexf.glsl
+++ b/java/Samples/res/raw/multitexf.glsl
@@ -7,6 +7,7 @@
    lowp vec4 col2 = texture2D(UNI_Tex2, t0).rgba;
    col0.xyz = col0.xyz*col1.xyz*1.5;
    col0.xyz = mix(col0.xyz, col2.xyz, col2.w);
+   col0.w = 0.5;
    gl_FragColor = col0;
 }
 
diff --git a/java/Samples/res/raw/shader2f.glsl b/java/Samples/res/raw/shader2f.glsl
new file mode 100644
index 0000000..5fc05f1
--- /dev/null
+++ b/java/Samples/res/raw/shader2f.glsl
@@ -0,0 +1,29 @@
+varying vec3 varWorldPos;
+varying vec3 varWorldNormal;
+varying vec2 varTex0;
+
+void main() {
+
+   vec3 V = normalize(-varWorldPos.xyz);
+   vec3 worldNorm = normalize(varWorldNormal);
+
+   vec3 light0Vec = normalize(UNI_light0_Posision.xyz - varWorldPos);
+   vec3 light0R = -reflect(light0Vec, worldNorm);
+   float light0_Diffuse = clamp(dot(worldNorm, light0Vec), 0.0, 1.0) * UNI_light0_Diffuse;
+   float light0Spec = clamp(dot(light0R, V), 0.001, 1.0);
+   float light0_Specular = pow(light0Spec, UNI_light0_CosinePower) * UNI_light0_Specular;
+
+   vec3 light1Vec = normalize(UNI_light1_Posision.xyz - varWorldPos);
+   vec3 light1R = reflect(light1Vec, worldNorm);
+   float light1_Diffuse = clamp(dot(worldNorm, light1Vec), 0.0, 1.0) * UNI_light1_Diffuse;
+   float light1Spec = clamp(dot(light1R, V), 0.001, 1.0);
+   float light1_Specular = pow(light1Spec, UNI_light1_CosinePower) * UNI_light1_Specular;
+
+   vec2 t0 = varTex0.xy;
+   lowp vec4 col = texture2D(UNI_Tex0, t0).rgba;
+   col.xyz = col.xyz * (light0_Diffuse * UNI_light0_DiffuseColor.xyz + light1_Diffuse * UNI_light1_DiffuseColor.xyz);
+   col.xyz += light0_Specular * UNI_light0_SpecularColor.xyz;
+   col.xyz += light1_Specular * UNI_light1_SpecularColor.xyz;
+   gl_FragColor = col;
+}
+
diff --git a/java/Samples/res/raw/shader2movev.glsl b/java/Samples/res/raw/shader2movev.glsl
new file mode 100644
index 0000000..68712e6
--- /dev/null
+++ b/java/Samples/res/raw/shader2movev.glsl
@@ -0,0 +1,22 @@
+varying vec3 varWorldPos;
+varying vec3 varWorldNormal;
+varying vec2 varTex0;
+
+// This is where actual shader code begins
+void main() {
+   vec4 objPos = ATTRIB_position;
+   vec3 oldPos = objPos.xyz;
+   objPos.xyz += 0.1*sin(objPos.xyz*2.0 + UNI_time);
+   objPos.xyz += 0.05*sin(objPos.xyz*4.0 + UNI_time*0.5);
+   objPos.xyz += 0.02*sin(objPos.xyz*7.0 + UNI_time*0.75);
+   vec4 worldPos = UNI_model * objPos;
+   gl_Position = UNI_proj * worldPos;
+
+   mat3 model3 = mat3(UNI_model[0].xyz, UNI_model[1].xyz, UNI_model[2].xyz);
+   vec3 worldNorm = model3 * (ATTRIB_normal + oldPos - objPos.xyz);
+   //vec3 worldNorm = model3 * ATTRIB_normal;
+
+   varWorldPos = worldPos.xyz;
+   varWorldNormal = worldNorm;
+   varTex0 = ATTRIB_texture0;
+}
diff --git a/java/Samples/res/raw/shader2v.glsl b/java/Samples/res/raw/shader2v.glsl
new file mode 100644
index 0000000..e6885a3
--- /dev/null
+++ b/java/Samples/res/raw/shader2v.glsl
@@ -0,0 +1,17 @@
+varying vec3 varWorldPos;
+varying vec3 varWorldNormal;
+varying vec2 varTex0;
+
+// This is where actual shader code begins
+void main() {
+   vec4 objPos = ATTRIB_position;
+   vec4 worldPos = UNI_model * objPos;
+   gl_Position = UNI_proj * worldPos;
+
+   mat3 model3 = mat3(UNI_model[0].xyz, UNI_model[1].xyz, UNI_model[2].xyz);
+   vec3 worldNorm = model3 * ATTRIB_normal;
+
+   varWorldPos = worldPos.xyz;
+   varWorldNormal = worldNorm;
+   varTex0 = ATTRIB_texture0;
+}
diff --git a/java/Samples/src/com/android/samples/RsBench.java b/java/Samples/src/com/android/samples/RsBench.java
new file mode 100644
index 0000000..5b9af6f
--- /dev/null
+++ b/java/Samples/src/com/android/samples/RsBench.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2008 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.samples;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings.System;
+import android.util.Config;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.ListView;
+
+import java.lang.Runtime;
+
+public class RsBench extends Activity {
+
+    private RsBenchView mView;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        // Create our Preview view and set it as the content of our
+        // Activity
+        mView = new RsBenchView(this);
+        setContentView(mView);
+    }
+
+    @Override
+    protected void onResume() {
+        // Ideally a game should implement onResume() and onPause()
+        // to take appropriate action when the activity looses focus
+        super.onResume();
+        mView.resume();
+    }
+
+    @Override
+    protected void onPause() {
+        // Ideally a game should implement onResume() and onPause()
+        // to take appropriate action when the activity looses focus
+        super.onPause();
+        mView.pause();
+    }
+
+}
+
diff --git a/java/Samples/src/com/android/samples/RsBenchRS.java b/java/Samples/src/com/android/samples/RsBenchRS.java
new file mode 100644
index 0000000..212e7a8
--- /dev/null
+++ b/java/Samples/src/com/android/samples/RsBenchRS.java
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2008 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.samples;
+
+import java.io.Writer;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.renderscript.*;
+import android.renderscript.Allocation.CubemapLayout;
+import android.renderscript.Program.TextureType;
+import android.renderscript.ProgramStore.DepthFunc;
+import android.renderscript.Sampler.Value;
+import android.util.Log;
+
+
+public class RsBenchRS {
+
+    int mWidth;
+    int mHeight;
+
+    public RsBenchRS() {
+    }
+
+    public void init(RenderScriptGL rs, Resources res, int width, int height) {
+        mRS = rs;
+        mRes = res;
+        mWidth = width;
+        mHeight = height;
+        mOptionsARGB.inScaled = false;
+        mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
+        mMode = 0;
+        mMaxModes = 0;
+        initRS();
+    }
+
+    private Resources mRes;
+    private RenderScriptGL mRS;
+
+    private Sampler mLinearClamp;
+    private Sampler mLinearWrap;
+    private Sampler mMipLinearWrap;
+    private Sampler mNearestClamp;
+    private Sampler mMipLinearAniso8;
+    private Sampler mMipLinearAniso15;
+
+    private ProgramStore mProgStoreBlendNoneDepth;
+    private ProgramStore mProgStoreBlendNone;
+    private ProgramStore mProgStoreBlendAlpha;
+    private ProgramStore mProgStoreBlendAdd;
+
+    private ProgramFragment mProgFragmentTexture;
+    private ProgramFragment mProgFragmentColor;
+
+    private ProgramVertex mProgVertex;
+    private ProgramVertex.MatrixAllocation mPVA;
+
+    // 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 ProgramVertex mProgVertexCube;
+    private ProgramFragment mProgFragmentCube;
+
+    private ProgramRaster mCullBack;
+    private ProgramRaster mCullFront;
+    private ProgramRaster mCullNone;
+
+    private Allocation mTexTorus;
+    private Allocation mTexOpaque;
+    private Allocation mTexTransparent;
+    private Allocation mTexChecker;
+    private Allocation mTexCube;
+
+    private Mesh m10by10Mesh;
+    private Mesh m100by100Mesh;
+    private Mesh mWbyHMesh;
+    private Mesh mTorus;
+
+    Font mFontSans;
+    Font mFontSerif;
+    Font mFontSerifBold;
+    Font mFontSerifItalic;
+    Font mFontSerifBoldItalic;
+    Font mFontMono;
+    private Allocation mTextAlloc;
+
+    private ScriptC_rsbench mScript;
+
+    private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
+
+    int mMode;
+    int mMaxModes;
+
+    public void onActionDown(int x, int y) {
+        mMode ++;
+        mMode = mMode % mMaxModes;
+        mScript.set_gDisplayMode(mMode);
+    }
+
+    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 void initProgramStore() {
+        // Use stock the stock program store object
+        mProgStoreBlendNoneDepth = ProgramStore.BLEND_NONE_DEPTH_TEST(mRS);
+        mProgStoreBlendNone = ProgramStore.BLEND_NONE_DEPTH_NO_DEPTH(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.setDitherEnable(false);
+        builder.setDepthMask(false);
+        mProgStoreBlendAlpha = builder.create();
+
+        mProgStoreBlendAdd = ProgramStore.BLEND_ADD_DEPTH_NO_DEPTH(mRS);
+
+        mScript.set_gProgStoreBlendNoneDepth(mProgStoreBlendNoneDepth);
+        mScript.set_gProgStoreBlendNone(mProgStoreBlendNone);
+        mScript.set_gProgStoreBlendAlpha(mProgStoreBlendAlpha);
+        mScript.set_gProgStoreBlendAdd(mProgStoreBlendAdd);
+    }
+
+    private void initProgramFragment() {
+
+        ProgramFragment.Builder texBuilder = new ProgramFragment.Builder(mRS);
+        texBuilder.setTexture(ProgramFragment.Builder.EnvMode.REPLACE,
+                              ProgramFragment.Builder.Format.RGBA, 0);
+        mProgFragmentTexture = texBuilder.create();
+        mProgFragmentTexture.bindSampler(mLinearClamp, 0);
+
+        ProgramFragment.Builder colBuilder = new ProgramFragment.Builder(mRS);
+        colBuilder.setVaryingColor(false);
+        mProgFragmentColor = colBuilder.create();
+
+        mScript.set_gProgFragmentColor(mProgFragmentColor);
+        mScript.set_gProgFragmentTexture(mProgFragmentTexture);
+    }
+
+    private void initProgramVertex() {
+        ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS);
+        mProgVertex = pvb.create();
+
+        mPVA = new ProgramVertex.MatrixAllocation(mRS);
+        mProgVertex.bindAllocation(mPVA);
+        mPVA.setupOrthoWindow(mWidth, mHeight);
+
+        mScript.set_gProgVertex(mProgVertex);
+    }
+
+    private void initCustomShaders() {
+        mVSConst = new ScriptField_VertexShaderConstants_s(mRS, 1);
+        mFSConst = new ScriptField_FragentShaderConstants_s(mRS, 1);
+        mScript.bind_gVSConstants(mVSConst);
+        mScript.bind_gFSConstants(mFSConst);
+
+        mVSConstPixel = new ScriptField_VertexShaderConstants3_s(mRS, 1);
+        mFSConstPixel = new ScriptField_FragentShaderConstants3_s(mRS, 1);
+        mScript.bind_gVSConstPixel(mVSConstPixel);
+        mScript.bind_gFSConstPixel(mFSConstPixel);
+
+        // Initialize the shader builder
+        ProgramVertex.ShaderBuilder pvbCustom = new ProgramVertex.ShaderBuilder(mRS);
+        // Specify the resource that contains the shader string
+        pvbCustom.setShader(mRes, R.raw.shaderv);
+        // Use a script field to spcify 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.ShaderBuilder pfbCustom = new ProgramFragment.ShaderBuilder(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);
+
+        // Cubemap test shaders
+        pvbCustom = new ProgramVertex.ShaderBuilder(mRS);
+        pvbCustom.setShader(mRes, R.raw.shadercubev);
+        pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
+        pvbCustom.addConstant(mVSConst.getAllocation().getType());
+        mProgVertexCube = pvbCustom.create();
+        mProgVertexCube.bindConstants(mVSConst.getAllocation(), 0);
+
+        pfbCustom = new ProgramFragment.ShaderBuilder(mRS);
+        pfbCustom.setShader(mRes, R.raw.shadercubef);
+        pfbCustom.addTexture(Program.TextureType.TEXTURE_CUBE);
+        mProgFragmentCube = pfbCustom.create();
+
+        pvbCustom = new ProgramVertex.ShaderBuilder(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.ShaderBuilder(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.ShaderBuilder(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.ShaderBuilder(mRS);
+        pfbCustom.setShader(mRes, R.raw.multitexf);
+        pfbCustom.setTextureCount(3);
+        mProgFragmentMultitex = pfbCustom.create();
+
+        mScript.set_gProgVertexCustom(mProgVertexCustom);
+        mScript.set_gProgFragmentCustom(mProgFragmentCustom);
+        mScript.set_gProgVertexCube(mProgVertexCube);
+        mScript.set_gProgFragmentCube(mProgFragmentCube);
+        mScript.set_gProgVertexPixelLight(mProgVertexPixelLight);
+        mScript.set_gProgVertexPixelLightMove(mProgVertexPixelLightMove);
+        mScript.set_gProgFragmentPixelLight(mProgFragmentPixelLight);
+        mScript.set_gProgFragmentMultitex(mProgFragmentMultitex);
+    }
+
+    private Allocation loadTextureRGB(int id) {
+        final Allocation allocation = Allocation.createFromBitmapResource(mRS, mRes,
+                id, Element.RGB_565(mRS), true);
+        allocation.uploadToTexture(0);
+        return allocation;
+    }
+
+    private Allocation loadTextureARGB(int id) {
+        Bitmap b = BitmapFactory.decodeResource(mRes, id, mOptionsARGB);
+        final Allocation allocation = Allocation.createFromBitmap(mRS, b, Element.RGBA_8888(mRS), true);
+        allocation.uploadToTexture(0);
+        return allocation;
+    }
+
+    private void loadImages() {
+        mTexTorus = loadTextureRGB(R.drawable.torusmap);
+        mTexOpaque = loadTextureRGB(R.drawable.data);
+        mTexTransparent = loadTextureARGB(R.drawable.leaf);
+        mTexChecker = loadTextureRGB(R.drawable.checker);
+        Bitmap b = BitmapFactory.decodeResource(mRes, R.drawable.cubemap_test);
+        mTexCube = Allocation.createCubemapFromBitmap(mRS, b, Element.RGB_565(mRS), false,
+                                                      Allocation.CubemapLayout.VERTICAL_FACE_LIST);
+        mTexCube.uploadToTexture(0);
+
+        mScript.set_gTexTorus(mTexTorus);
+        mScript.set_gTexOpaque(mTexOpaque);
+        mScript.set_gTexTransparent(mTexTransparent);
+        mScript.set_gTexChecker(mTexChecker);
+        mScript.set_gTexCube(mTexCube);
+    }
+
+    private void initFonts() {
+        // Sans font by family name
+        mFontSans = Font.createFromFamily(mRS, mRes, "sans-serif", Font.Style.NORMAL, 8);
+        // Create font by file name
+        mFontSerif = Font.create(mRS, mRes, "DroidSerif-Regular.ttf", 8);
+        // Create fonts by family and style
+        mFontSerifBold = Font.createFromFamily(mRS, mRes, "serif", Font.Style.BOLD, 8);
+        mFontSerifItalic = Font.createFromFamily(mRS, mRes, "serif", Font.Style.ITALIC, 8);
+        mFontSerifBoldItalic = Font.createFromFamily(mRS, mRes, "serif", Font.Style.BOLD_ITALIC, 8);
+        mFontMono = Font.createFromFamily(mRS, mRes, "mono", Font.Style.NORMAL, 8);
+
+        mTextAlloc = Allocation.createFromString(mRS, "String from allocation", Allocation.USAGE_SCRIPT);
+
+        mScript.set_gFontSans(mFontSans);
+        mScript.set_gFontSerif(mFontSerif);
+        mScript.set_gFontSerifBold(mFontSerifBold);
+        mScript.set_gFontSerifItalic(mFontSerifItalic);
+        mScript.set_gFontSerifBoldItalic(mFontSerifBoldItalic);
+        mScript.set_gFontMono(mFontMono);
+        mScript.set_gTextAlloc(mTextAlloc);
+    }
+
+    private void initMesh() {
+        m10by10Mesh = getMbyNMesh(mWidth, mHeight, 10, 10);
+        mScript.set_g10by10Mesh(m10by10Mesh);
+        m100by100Mesh = getMbyNMesh(mWidth, mHeight, 100, 100);
+        mScript.set_g100by100Mesh(m100by100Mesh);
+        mWbyHMesh= getMbyNMesh(mWidth, mHeight, mWidth/4, mHeight/4);
+        mScript.set_gWbyHMesh(mWbyHMesh);
+
+        FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.torus);
+        FileA3D.IndexEntry entry = model.getIndexEntry(0);
+        if (entry == null || entry.getClassID() != FileA3D.ClassID.MESH) {
+            Log.e("rs", "could not load model");
+        } else {
+            mTorus = (Mesh)entry.getObject();
+            mScript.set_gTorusMesh(mTorus);
+        }
+    }
+
+    private void initSamplers() {
+        Sampler.Builder bs = new Sampler.Builder(mRS);
+        bs.setMin(Sampler.Value.LINEAR);
+        bs.setMag(Sampler.Value.LINEAR);
+        bs.setWrapS(Sampler.Value.WRAP);
+        bs.setWrapT(Sampler.Value.WRAP);
+        mLinearWrap = bs.create();
+
+        mLinearClamp = Sampler.CLAMP_LINEAR(mRS);
+        mNearestClamp = Sampler.CLAMP_NEAREST(mRS);
+        mMipLinearWrap = Sampler.WRAP_LINEAR_MIP_LINEAR(mRS);
+
+        bs = new Sampler.Builder(mRS);
+        bs.setMin(Sampler.Value.LINEAR_MIP_LINEAR);
+        bs.setMag(Sampler.Value.LINEAR);
+        bs.setWrapS(Sampler.Value.WRAP);
+        bs.setWrapT(Sampler.Value.WRAP);
+        bs.setAnisotropy(8.0f);
+        mMipLinearAniso8 = bs.create();
+        bs.setAnisotropy(15.0f);
+        mMipLinearAniso15 = bs.create();
+
+        mScript.set_gLinearClamp(mLinearClamp);
+        mScript.set_gLinearWrap(mLinearWrap);
+        mScript.set_gMipLinearWrap(mMipLinearWrap);
+        mScript.set_gMipLinearAniso8(mMipLinearAniso8);
+        mScript.set_gMipLinearAniso15(mMipLinearAniso15);
+        mScript.set_gNearestClamp(mNearestClamp);
+    }
+
+    private void initProgramRaster() {
+        mCullBack = ProgramRaster.CULL_BACK(mRS);
+        mCullFront = ProgramRaster.CULL_FRONT(mRS);
+        mCullNone = ProgramRaster.CULL_NONE(mRS);
+
+        mScript.set_gCullBack(mCullBack);
+        mScript.set_gCullFront(mCullFront);
+        mScript.set_gCullNone(mCullNone);
+    }
+
+    private void initRS() {
+
+        mScript = new ScriptC_rsbench(mRS, mRes, R.raw.rsbench);
+
+        mMaxModes = mScript.get_gMaxModes();
+
+        initSamplers();
+        initProgramStore();
+        initProgramFragment();
+        initProgramVertex();
+        initFonts();
+        loadImages();
+        initMesh();
+        initProgramRaster();
+        initCustomShaders();
+
+        mRS.bindRootScript(mScript);
+    }
+}
+
+
+
diff --git a/java/Samples/src/com/android/samples/RsBenchView.java b/java/Samples/src/com/android/samples/RsBenchView.java
new file mode 100644
index 0000000..4283a42
--- /dev/null
+++ b/java/Samples/src/com/android/samples/RsBenchView.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2008 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.samples;
+
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.concurrent.Semaphore;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+import android.renderscript.RenderScriptGL;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+public class RsBenchView extends RSSurfaceView {
+
+    public RsBenchView(Context context) {
+        super(context);
+        //setFocusable(true);
+    }
+
+    private RenderScriptGL mRS;
+    private RsBenchRS mRender;
+
+
+    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+        super.surfaceChanged(holder, format, w, h);
+        if (mRS == null) {
+            RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
+            sc.setDepth(16, 24);
+            mRS = createRenderScriptGL(sc);
+            mRS.setSurface(holder, w, h);
+            mRender = new RsBenchRS();
+            mRender.init(mRS, getResources(), w, h);
+        }
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        if (mRS != null) {
+            mRS = null;
+            destroyRenderScriptGL();
+        }
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event)
+    {
+        // break point at here
+        // this method doesn't work when 'extends View' include 'extends ScrollView'.
+        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;
+    }
+}
+
+
diff --git a/java/Samples/src/com/android/samples/rsbench.rs b/java/Samples/src/com/android/samples/rsbench.rs
new file mode 100644
index 0000000..87f2f29
--- /dev/null
+++ b/java/Samples/src/com/android/samples/rsbench.rs
@@ -0,0 +1,845 @@
+// Copyright (C) 2009 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.samples)
+
+#include "rs_graphics.rsh"
+#include "shader_def.rsh"
+
+const int gMaxModes = 23;
+
+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 gTexCube;
+
+rs_mesh g10by10Mesh;
+rs_mesh g100by100Mesh;
+rs_mesh gWbyHMesh;
+rs_mesh gTorusMesh;
+
+rs_font gFontSans;
+rs_font gFontSerif;
+rs_font gFontSerifBold;
+rs_font gFontSerifItalic;
+rs_font gFontSerifBoldItalic;
+rs_font gFontMono;
+rs_allocation gTextAlloc;
+
+int gDisplayMode;
+
+rs_sampler gLinearClamp;
+rs_sampler gLinearWrap;
+rs_sampler gMipLinearWrap;
+rs_sampler gMipLinearAniso8;
+rs_sampler gMipLinearAniso15;
+rs_sampler gNearestClamp;
+
+rs_program_raster gCullBack;
+rs_program_raster gCullFront;
+rs_program_raster gCullNone;
+
+// Custom vertex shader compunents
+VertexShaderConstants *gVSConstants;
+FragentShaderConstants *gFSConstants;
+VertexShaderConstants3 *gVSConstPixel;
+FragentShaderConstants3 *gFSConstPixel;
+// Export these out to easily set the inputs to shader
+VertexShaderInputs *gVSInputs;
+// Custom shaders we use for lighting
+rs_program_vertex gProgVertexCustom;
+rs_program_fragment gProgFragmentCustom;
+rs_program_vertex gProgVertexPixelLight;
+rs_program_vertex gProgVertexPixelLightMove;
+rs_program_fragment gProgFragmentPixelLight;
+rs_program_vertex gProgVertexCube;
+rs_program_fragment gProgFragmentCube;
+rs_program_fragment gProgFragmentMultitex;
+
+float gDt = 0;
+
+void init() {
+}
+
+static const char *sampleText = "This is a sample of small text for performace";
+// Offsets for multiple layer of text
+static int textOffsets[] = { 0,  0, -5, -5, 5,  5, -8, -8, 8,  8};
+static float textColors[] = {1.0f, 1.0f, 1.0f, 1.0f,
+                             0.5f, 0.7f, 0.5f, 1.0f,
+                             0.7f, 0.5f, 0.5f, 1.0f,
+                             0.5f, 0.5f, 0.7f, 1.0f,
+                             0.5f, 0.6f, 0.7f, 1.0f,
+};
+
+void displayFontSamples(int fillNum) {
+
+    uint width = rsgGetWidth();
+    uint height = rsgGetHeight();
+    int left = 0, right = 0, top = 0, bottom = 0;
+    rsgMeasureText(sampleText, &left, &right, &top, &bottom);
+
+    int textHeight = top - bottom;
+    int textWidth = right - left;
+    int numVerticalLines = height / textHeight;
+    int yPos = top;
+
+    int xOffset = 0, yOffset = 0;
+    rsgBindFont(gFontSans); //rsgBindFont(gFontSerif); rsgBindFont(gFontSerifBold); rsgBindFont(gFontSerifBoldItalic); rsgBindFont(gFontSans);
+
+    for(int fillI = 0; fillI < fillNum; fillI ++) {
+        xOffset = textOffsets[fillI * 2];
+        yOffset = textOffsets[fillI * 2 + 1];
+        float *colPtr = textColors + fillI * 4;
+        rsgFontColor(colPtr[0], colPtr[1], colPtr[2], colPtr[3]);
+        for (int h = 0; h < 4; h ++) {
+            yPos = top + yOffset;
+            for (int v = 0; v < numVerticalLines; v ++) {
+                rsgDrawText(sampleText, xOffset + textWidth * h, yPos);
+                yPos += textHeight;
+            }
+        }
+    }
+}
+
+void bindProgramVertexOrtho() {
+    // Default vertex sahder
+    rsgBindProgramVertex(gProgVertex);
+    // Setup the projectioni matrix
+    rs_matrix4x4 proj;
+    rsMatrixLoadOrtho(&proj, 0, rsgGetWidth(), rsgGetHeight(), 0, -500, 500);
+    rsgProgramVertexLoadProjectionMatrix(&proj);
+}
+
+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 = 10 * i, startY = 10 * i;
+        float width = rsgGetWidth() - startX, height = rsgGetHeight() - 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 displayBlendingSamples() {
+    int i;
+
+    bindProgramVertexOrtho();
+    rs_matrix4x4 matrix;
+    rsMatrixLoadIdentity(&matrix);
+    rsgProgramVertexLoadModelMatrix(&matrix);
+
+    rsgBindProgramFragment(gProgFragmentColor);
+
+    rsgBindProgramStore(gProgStoreBlendNone);
+    for (i = 0; i < 3; i ++) {
+        float iPlusOne = (float)(i + 1);
+        rsgProgramFragmentConstantColor(gProgFragmentColor,
+                                        0.1f*iPlusOne, 0.2f*iPlusOne, 0.3f*iPlusOne, 1);
+        float yPos = 150 * (float)i;
+        rsgDrawRect(0, yPos, 200, yPos + 200, 0);
+    }
+
+    rsgBindProgramStore(gProgStoreBlendAlpha);
+    for (i = 0; i < 3; i ++) {
+        float iPlusOne = (float)(i + 1);
+        rsgProgramFragmentConstantColor(gProgFragmentColor,
+                                        0.2f*iPlusOne, 0.3f*iPlusOne, 0.1f*iPlusOne, 0.5);
+        float yPos = 150 * (float)i;
+        rsgDrawRect(150, yPos, 350, yPos + 200, 0);
+    }
+
+    rsgBindProgramStore(gProgStoreBlendAdd);
+    for (i = 0; i < 3; i ++) {
+        float iPlusOne = (float)(i + 1);
+        rsgProgramFragmentConstantColor(gProgFragmentColor,
+                                        0.3f*iPlusOne, 0.1f*iPlusOne, 0.2f*iPlusOne, 0.5);
+        float yPos = 150 * (float)i;
+        rsgDrawRect(300, yPos, 500, yPos + 200, 0);
+    }
+
+
+    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
+    rsgBindFont(gFontMono);
+    rsgDrawText("No Blending", 10, 50);
+    rsgDrawText("Alpha Blending", 160, 150);
+    rsgDrawText("Additive Blending", 320, 250);
+
+}
+
+void displayMeshSamples(int meshNum) {
+
+    bindProgramVertexOrtho();
+    rs_matrix4x4 matrix;
+    rsMatrixLoadTranslate(&matrix, rsgGetWidth()/2, rsgGetHeight()/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 displayTextureSamplers() {
+
+    bindProgramVertexOrtho();
+    rs_matrix4x4 matrix;
+    rsMatrixLoadIdentity(&matrix);
+    rsgProgramVertexLoadModelMatrix(&matrix);
+
+    // Fragment shader with texture
+    rsgBindProgramStore(gProgStoreBlendNone);
+    rsgBindProgramFragment(gProgFragmentTexture);
+    rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque);
+
+    // Linear clamp
+    rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+    float startX = 0, startY = 0;
+    float width = 300, height = 300;
+    rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
+                         startX, startY + height, 0, 0, 1.1,
+                         startX + width, startY + height, 0, 1.1, 1.1,
+                         startX + width, startY, 0, 1.1, 0);
+
+    // Linear Wrap
+    rsgBindSampler(gProgFragmentTexture, 0, gLinearWrap);
+    startX = 0; startY = 300;
+    width = 300; height = 300;
+    rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
+                         startX, startY + height, 0, 0, 1.1,
+                         startX + width, startY + height, 0, 1.1, 1.1,
+                         startX + width, startY, 0, 1.1, 0);
+
+    // Nearest
+    rsgBindSampler(gProgFragmentTexture, 0, gNearestClamp);
+    startX = 300; startY = 0;
+    width = 300; height = 300;
+    rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
+                         startX, startY + height, 0, 0, 1.1,
+                         startX + width, startY + height, 0, 1.1, 1.1,
+                         startX + width, startY, 0, 1.1, 0);
+
+    rsgBindSampler(gProgFragmentTexture, 0, gMipLinearWrap);
+    startX = 300; startY = 300;
+    width = 300; height = 300;
+    rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
+                         startX, startY + height, 0, 0, 1.5,
+                         startX + width, startY + height, 0, 1.5, 1.5,
+                         startX + width, startY, 0, 1.5, 0);
+
+    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
+    rsgBindFont(gFontMono);
+    rsgDrawText("Filtering: linear clamp", 10, 290);
+    rsgDrawText("Filtering: linear wrap", 10, 590);
+    rsgDrawText("Filtering: nearest clamp", 310, 290);
+    rsgDrawText("Filtering: miplinear wrap", 310, 590);
+}
+
+float gTorusRotation = 0;
+static void drawToruses(int numMeshes) {
+    rs_matrix4x4 matrix;
+
+    if (numMeshes == 1) {
+        rsMatrixLoadTranslate(&matrix, 0.0f, 0.0f, -7.5f);
+        rsMatrixRotate(&matrix, gTorusRotation, 1.0f, 0.0f, 0.0f);
+        rsgProgramVertexLoadModelMatrix(&matrix);
+        rsgDrawMesh(gTorusMesh);
+        return;
+    }
+
+    if (numMeshes == 2) {
+        rsMatrixLoadTranslate(&matrix, -1.6f, 0.0f, -7.5f);
+        rsMatrixRotate(&matrix, gTorusRotation, 1.0f, 0.0f, 0.0f);
+        rsgProgramVertexLoadModelMatrix(&matrix);
+        rsgDrawMesh(gTorusMesh);
+
+        rsMatrixLoadTranslate(&matrix, 1.6f, 0.0f, -7.5f);
+        rsMatrixRotate(&matrix, gTorusRotation, 1.0f, 0.0f, 0.0f);
+        rsgProgramVertexLoadModelMatrix(&matrix);
+        rsgDrawMesh(gTorusMesh);
+        return;
+    }
+
+    float startX = -5.0f;
+    float startY = -1.5f;
+    float startZ = -15.0f;
+    float dist = 3.2f;
+
+    for (int h = 0; h < 4; h ++) {
+        for (int v = 0; v < 2; v ++) {
+            // Position our model on the screen
+            rsMatrixLoadTranslate(&matrix, startX + dist * h, startY + dist * v, startZ);
+            rsMatrixRotate(&matrix, gTorusRotation, 1.0f, 0.0f, 0.0f);
+            rsgProgramVertexLoadModelMatrix(&matrix);
+            rsgDrawMesh(gTorusMesh);
+        }
+    }
+}
+
+
+// Quick hack to get some geometry numbers
+void displaySimpleGeoSamples(bool useTexture, int numMeshes) {
+    rsgBindProgramVertex(gProgVertex);
+    rsgBindProgramRaster(gCullBack);
+    // Setup the projectioni matrix with 60 degree field of view
+    rs_matrix4x4 proj;
+    float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
+    rsMatrixLoadPerspective(&proj, 30.0f, aspect, 0.1f, 100.0f);
+    rsgProgramVertexLoadProjectionMatrix(&proj);
+
+    // Fragment shader with texture
+    rsgBindProgramStore(gProgStoreBlendNoneDepth);
+    if (useTexture) {
+        rsgBindProgramFragment(gProgFragmentTexture);
+    } else {
+        rsgBindProgramFragment(gProgFragmentColor);
+        rsgProgramFragmentConstantColor(gProgFragmentColor, 0.1, 0.7, 0.1, 1);
+    }
+    rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+    rsgBindTexture(gProgFragmentTexture, 0, gTexTorus);
+
+    // Aplly a rotation to our mesh
+    gTorusRotation += 50.0f * gDt;
+    if (gTorusRotation > 360.0f) {
+        gTorusRotation -= 360.0f;
+    }
+
+    drawToruses(numMeshes);
+}
+
+float gLight0Rotation = 0;
+float gLight1Rotation = 0;
+
+void setupCustomShaderLights() {
+    float4 light0Pos = {-5.0f, 5.0f, -10.0f, 1.0f};
+    float4 light1Pos = {2.0f, 5.0f, 15.0f, 1.0f};
+    float4 light0DiffCol = {0.9f, 0.7f, 0.7f, 1.0f};
+    float4 light0SpecCol = {0.9f, 0.6f, 0.6f, 1.0f};
+    float4 light1DiffCol = {0.5f, 0.5f, 0.9f, 1.0f};
+    float4 light1SpecCol = {0.5f, 0.5f, 0.9f, 1.0f};
+
+    gLight0Rotation += 50.0f * gDt;
+    if (gLight0Rotation > 360.0f) {
+        gLight0Rotation -= 360.0f;
+    }
+    gLight1Rotation -= 50.0f * gDt;
+    if (gLight1Rotation > 360.0f) {
+        gLight1Rotation -= 360.0f;
+    }
+
+    rs_matrix4x4 l0Mat;
+    rsMatrixLoadRotate(&l0Mat, gLight0Rotation, 1.0f, 0.0f, 0.0f);
+    light0Pos = rsMatrixMultiply(&l0Mat, light0Pos);
+    rs_matrix4x4 l1Mat;
+    rsMatrixLoadRotate(&l1Mat, gLight1Rotation, 0.0f, 0.0f, 1.0f);
+    light1Pos = rsMatrixMultiply(&l1Mat, light1Pos);
+
+    // Set light 0 properties
+    gVSConstants->light0_Posision = light0Pos;
+    gVSConstants->light0_Diffuse = 1.0f;
+    gVSConstants->light0_Specular = 0.5f;
+    gVSConstants->light0_CosinePower = 10.0f;
+    // Set light 1 properties
+    gVSConstants->light1_Posision = light1Pos;
+    gVSConstants->light1_Diffuse = 1.0f;
+    gVSConstants->light1_Specular = 0.7f;
+    gVSConstants->light1_CosinePower = 25.0f;
+    rsAllocationMarkDirty(rsGetAllocation(gVSConstants));
+
+    // Update fragmetn shader constants
+    // Set light 0 colors
+    gFSConstants->light0_DiffuseColor = light0DiffCol;
+    gFSConstants->light0_SpecularColor = light0SpecCol;
+    // Set light 1 colors
+    gFSConstants->light1_DiffuseColor = light1DiffCol;
+    gFSConstants->light1_SpecularColor = light1SpecCol;
+    rsAllocationMarkDirty(rsGetAllocation(gFSConstants));
+
+    // Set light 0 properties for per pixel lighting
+    gFSConstPixel->light0_Posision = light0Pos;
+    gFSConstPixel->light0_Diffuse = 1.0f;
+    gFSConstPixel->light0_Specular = 0.5f;
+    gFSConstPixel->light0_CosinePower = 10.0f;
+    gFSConstPixel->light0_DiffuseColor = light0DiffCol;
+    gFSConstPixel->light0_SpecularColor = light0SpecCol;
+    // Set light 1 properties
+    gFSConstPixel->light1_Posision = light1Pos;
+    gFSConstPixel->light1_Diffuse = 1.0f;
+    gFSConstPixel->light1_Specular = 0.7f;
+    gFSConstPixel->light1_CosinePower = 25.0f;
+    gFSConstPixel->light1_DiffuseColor = light1DiffCol;
+    gFSConstPixel->light1_SpecularColor = light1SpecCol;
+    rsAllocationMarkDirty(rsGetAllocation(gFSConstPixel));
+}
+
+void displayCustomShaderSamples(int numMeshes) {
+
+    // Update vertex shader constants
+    // Load model matrix
+    // Aplly a rotation to our mesh
+    gTorusRotation += 50.0f * gDt;
+    if (gTorusRotation > 360.0f) {
+        gTorusRotation -= 360.0f;
+    }
+
+    // Setup the projectioni matrix
+    float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
+    rsMatrixLoadPerspective(&gVSConstants->proj, 30.0f, aspect, 0.1f, 100.0f);
+    setupCustomShaderLights();
+
+    rsgBindProgramVertex(gProgVertexCustom);
+
+    // Fragment shader with texture
+    rsgBindProgramStore(gProgStoreBlendNoneDepth);
+    rsgBindProgramFragment(gProgFragmentCustom);
+    rsgBindSampler(gProgFragmentCustom, 0, gLinearClamp);
+    rsgBindTexture(gProgFragmentCustom, 0, gTexTorus);
+
+    // Use back face culling
+    rsgBindProgramRaster(gCullBack);
+
+    rs_matrix4x4 matrix;
+
+    if (numMeshes == 1) {
+        rsMatrixLoadTranslate(&gVSConstants->model, 0.0f, 0.0f, -7.5f);
+        rsMatrixRotate(&gVSConstants->model, gTorusRotation, 1.0f, 0.0f, 0.0f);
+        rsMatrixRotate(&gVSConstants->model, gTorusRotation, 0.0f, 0.0f, 1.0f);
+        rsAllocationMarkDirty(rsGetAllocation(gVSConstants));
+
+        rsgDrawMesh(gTorusMesh);
+        return;
+    }
+
+    if (numMeshes == 2) {
+        rsMatrixLoadTranslate(&gVSConstants->model, -1.6f, 0.0f, -7.5f);
+        rsMatrixRotate(&gVSConstants->model, gTorusRotation, 1.0f, 0.0f, 0.0f);
+        rsMatrixRotate(&gVSConstants->model, gTorusRotation, 0.0f, 0.0f, 1.0f);
+        rsAllocationMarkDirty(rsGetAllocation(gVSConstants));
+        rsgDrawMesh(gTorusMesh);
+
+        rsMatrixLoadTranslate(&gVSConstants->model, 1.6f, 0.0f, -7.5f);
+        rsMatrixRotate(&gVSConstants->model, gTorusRotation, 1.0f, 0.0f, 0.0f);
+        rsMatrixRotate(&gVSConstants->model, gTorusRotation, 0.0f, 0.0f, 1.0f);
+        rsAllocationMarkDirty(rsGetAllocation(gVSConstants));
+        rsgDrawMesh(gTorusMesh);
+        return;
+    }
+
+    float startX = -5.0f;
+    float startY = -1.5f;
+    float startZ = -15.0f;
+    float dist = 3.2f;
+
+    for (int h = 0; h < 4; h ++) {
+        for (int v = 0; v < 2; v ++) {
+            // Position our model on the screen
+            rsMatrixLoadTranslate(&gVSConstants->model, startX + dist * h, startY + dist * v, startZ);
+            rsMatrixRotate(&gVSConstants->model, gTorusRotation, 1.0f, 0.0f, 0.0f);
+            rsMatrixRotate(&gVSConstants->model, gTorusRotation, 0.0f, 0.0f, 1.0f);
+            rsAllocationMarkDirty(rsGetAllocation(gVSConstants));
+            rsgDrawMesh(gTorusMesh);
+        }
+    }
+}
+
+void displayPixelLightSamples(int numMeshes) {
+
+    // Update vertex shader constants
+    // Load model matrix
+    // Aplly a rotation to our mesh
+    gTorusRotation += 20.0f * gDt;
+    if (gTorusRotation > 360.0f) {
+        gTorusRotation -= 360.0f;
+    }
+
+    //gTorusRotation = 45.0f;
+
+    gVSConstPixel->time = rsUptimeMillis()*0.005;
+
+    // Setup the projectioni matrix
+    float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
+    rsMatrixLoadPerspective(&gVSConstPixel->proj, 30.0f, aspect, 0.1f, 100.0f);
+    setupCustomShaderLights();
+
+    rsgBindProgramVertex(gProgVertexPixelLight);
+
+    // Fragment shader with texture
+    rsgBindProgramStore(gProgStoreBlendNoneDepth);
+    rsgBindProgramFragment(gProgFragmentPixelLight);
+    rsgBindSampler(gProgFragmentPixelLight, 0, gLinearClamp);
+    rsgBindTexture(gProgFragmentPixelLight, 0, gTexTorus);
+
+    // Use back face culling
+    rsgBindProgramRaster(gCullBack);
+
+    rs_matrix4x4 matrix;
+
+    if (numMeshes == 1) {
+        rsMatrixLoadTranslate(&gVSConstPixel->model, 0.0f, 0.0f, -7.5f);
+        rsMatrixRotate(&gVSConstPixel->model, gTorusRotation, 1.0f, 0.0f, 0.0f);
+        rsMatrixRotate(&gVSConstPixel->model, gTorusRotation, 0.0f, 0.0f, 1.0f);
+        rsAllocationMarkDirty(rsGetAllocation(gVSConstPixel));
+
+        rsgDrawMesh(gTorusMesh);
+        return;
+    }
+
+    if (numMeshes == 2) {
+        rsMatrixLoadTranslate(&gVSConstPixel->model, -1.6f, 0.0f, -7.5f);
+        rsMatrixRotate(&gVSConstPixel->model, gTorusRotation, 1.0f, 0.0f, 0.0f);
+        rsMatrixRotate(&gVSConstPixel->model, gTorusRotation, 0.0f, 0.0f, 1.0f);
+        rsAllocationMarkDirty(rsGetAllocation(gVSConstPixel));
+        rsgDrawMesh(gTorusMesh);
+
+        rsMatrixLoadTranslate(&gVSConstPixel->model, 1.6f, 0.0f, -7.5f);
+        rsMatrixRotate(&gVSConstPixel->model, gTorusRotation, 1.0f, 0.0f, 0.0f);
+        rsMatrixRotate(&gVSConstPixel->model, gTorusRotation, 0.0f, 0.0f, 1.0f);
+        rsAllocationMarkDirty(rsGetAllocation(gVSConstPixel));
+        rsgDrawMesh(gTorusMesh);
+        return;
+    }
+
+    float startX = -5.0f;
+    float startY = -1.5f;
+    float startZ = -15.0f;
+    float dist = 3.2f;
+
+    for (int h = 0; h < 4; h ++) {
+        for (int v = 0; v < 2; v ++) {
+            // Position our model on the screen
+            rsMatrixLoadTranslate(&gVSConstPixel->model, startX + dist * h, startY + dist * v, startZ);
+            rsMatrixRotate(&gVSConstPixel->model, gTorusRotation, 1.0f, 0.0f, 0.0f);
+            rsMatrixRotate(&gVSConstPixel->model, gTorusRotation, 0.0f, 0.0f, 1.0f);
+            rsAllocationMarkDirty(rsGetAllocation(gVSConstPixel));
+            rsgDrawMesh(gTorusMesh);
+        }
+    }
+}
+
+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 = rsgGetWidth() - startX, height = rsgGetHeight() - 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);
+    }
+}
+
+float gAnisoTime = 0.0f;
+uint anisoMode = 0;
+void displayAnisoSample() {
+
+    gAnisoTime += gDt;
+
+    rsgBindProgramVertex(gProgVertex);
+    float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
+    rs_matrix4x4 proj;
+    rsMatrixLoadPerspective(&proj, 30.0f, aspect, 0.1f, 100.0f);
+    rsgProgramVertexLoadProjectionMatrix(&proj);
+
+    rs_matrix4x4 matrix;
+    // Fragment shader with texture
+    rsgBindProgramStore(gProgStoreBlendNone);
+    rsgBindProgramFragment(gProgFragmentTexture);
+    rsMatrixLoadTranslate(&matrix, 0.0f, 0.0f, -10.0f);
+    rsMatrixRotate(&matrix, -80, 1.0f, 0.0f, 0.0f);
+    rsgProgramVertexLoadModelMatrix(&matrix);
+
+    rsgBindProgramRaster(gCullNone);
+
+    rsgBindTexture(gProgFragmentTexture, 0, gTexChecker);
+
+    if (gAnisoTime >= 5.0f) {
+        gAnisoTime = 0.0f;
+        anisoMode ++;
+        anisoMode = anisoMode % 3;
+    }
+
+    if (anisoMode == 0) {
+        rsgBindSampler(gProgFragmentTexture, 0, gMipLinearAniso8);
+    } else if (anisoMode == 1) {
+        rsgBindSampler(gProgFragmentTexture, 0, gMipLinearAniso15);
+    } else {
+        rsgBindSampler(gProgFragmentTexture, 0, gMipLinearWrap);
+    }
+
+    float startX = -15;
+    float startY = -15;
+    float width = 30;
+    float height = 30;
+    rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
+                         startX, startY + height, 0, 0, 10,
+                         startX + width, startY + height, 0, 10, 10,
+                         startX + width, startY, 0, 10, 0);
+
+    rsgBindProgramRaster(gCullBack);
+
+    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
+    rsgBindFont(gFontMono);
+    if (anisoMode == 0) {
+        rsgDrawText("Anisotropic filtering 8", 10, 40);
+    } else if (anisoMode == 1) {
+        rsgDrawText("Anisotropic filtering 15", 10, 40);
+    } else {
+        rsgDrawText("Miplinear filtering", 10, 40);
+    }
+}
+
+static bool checkInit() {
+
+    static int countdown = 5;
+
+    if (countdown == 0) {
+        gDt = 0;
+        countdown --;
+    }
+    // Perform all the uploads so we only measure rendered time
+    if(countdown > 1) {
+        displayFontSamples(5);
+        displaySingletexFill(true, 3);
+        displayBlendingSamples();
+        displayMeshSamples(0);
+        displayMeshSamples(1);
+        displayMeshSamples(2);
+        displayTextureSamplers();
+        displayMultitextureSample(true, 5);
+        displayAnisoSample();
+        countdown --;
+        rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f);
+
+        // Now use text metrics to center the text
+        uint width = rsgGetWidth();
+        uint height = rsgGetHeight();
+        int left = 0, right = 0, top = 0, bottom = 0;
+
+        rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f);
+        rsgBindFont(gFontSerifBoldItalic);
+
+        const char* text = "Initializing";
+        rsgMeasureText(text, &left, &right, &top, &bottom);
+        int centeredPosX = width / 2 - (right - left) / 2;
+        int centeredPosY = height / 2 - (top - bottom) / 2;
+        rsgDrawText(text, centeredPosX, centeredPosY);
+
+        return false;
+    }
+
+    return true;
+}
+
+static int frameCount = 0;
+static int totalFramesRendered = 0;
+static int benchMode = 0;
+
+#define testTime 10.0f
+static float curTestTime = testTime;
+
+static const char *testNames[] = {
+    "Finished text fill 1",
+    "Finished text fill 2",
+    "Finished text fill 3",
+    "Finished text fill 4",
+    "Finished text fill 5",
+    "Finished 25.6k geo flat color",
+    "Finished 51.2k geo flat color",
+    "Finished 204.8k geo raster load flat color",
+    "Finished 25.6k geo texture",
+    "Finished 51.2k geo texture",
+    "Finished 204.8k geo raster load texture",
+    "Finished full screen mesh 10 by 10",
+    "Finished full screen mesh 100 by 100",
+    "Finished full screen mesh W / 4 by H / 4",
+    "Finished 25.6k geo heavy vertex",
+    "Finished 51.2k geo heavy vertex",
+    "Finished 204.8k geo raster load heavy vertex",
+    "Finished singletexture 5x fill",
+    "Finished 3tex multitexture 5x fill",
+    "Finished blend singletexture 5x fill",
+    "Finished blend 3tex multitexture 5x fill",
+    "Finished 25.6k geo heavy fragment",
+    "Finished 51.2k geo heavy fragment",
+    "Finished 204.8k geo raster load heavy fragment",
+    "Finished simpleGeo",
+    "Finished simpleGeo",
+    "Finished simpleGeo",
+    "Finished simpleGeo",
+    "Finished simpleGeo",
+    "Finished simpleGeo",
+};
+
+int root(int launchID) {
+
+    gDt = rsGetDt();
+
+    rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f);
+    rsgClearDepth(1.0f);
+
+    if(!checkInit()) {
+        return 1;
+    }
+
+    /*displayPixelLightSamples(1);
+    return 1;*/
+
+    curTestTime -= gDt;
+    if(curTestTime < 0.0f) {
+        float fps = (float)(frameCount) / (testTime - curTestTime);
+        rsDebug(testNames[benchMode], fps);
+        benchMode ++;
+        curTestTime = testTime;
+        totalFramesRendered += frameCount;
+        frameCount = 0;
+        gTorusRotation = 0;
+
+        if (benchMode > gMaxModes) {
+            benchMode = 0;
+        }
+    }
+
+    switch (benchMode) {
+    case 0:
+        displayFontSamples(1);
+        break;
+    case 1:
+        displayFontSamples(2);
+        break;
+    case 2:
+        displayFontSamples(3);
+        break;
+    case 3:
+        displayFontSamples(4);
+        break;
+    case 4:
+        displayFontSamples(5);
+        break;
+    case 5:
+        displaySimpleGeoSamples(false, 1);
+        break;
+    case 6:
+        displaySimpleGeoSamples(false, 2);
+        break;
+    case 7:
+        displaySimpleGeoSamples(false, 8);
+        break;
+    case 8:
+        displaySimpleGeoSamples(true, 1);
+        break;
+    case 9:
+        displaySimpleGeoSamples(true, 2);
+        break;
+    case 10:
+        displaySimpleGeoSamples(true, 8);
+        break;
+    case 11:
+        displayMeshSamples(0);
+        break;
+    case 12:
+        displayMeshSamples(1);
+        break;
+    case 13:
+        displayMeshSamples(2);
+        break;
+    case 14:
+        displayCustomShaderSamples(1);
+        break;
+    case 15:
+        displayCustomShaderSamples(2);
+        break;
+    case 16:
+        displayCustomShaderSamples(8);
+        break;
+    case 17:
+        displaySingletexFill(false, 5);
+        break;
+    case 18:
+        displayMultitextureSample(false, 5);
+        break;
+    case 19:
+        displaySingletexFill(true, 5);
+        break;
+    case 20:
+        displayMultitextureSample(true, 5);
+        break;
+    case 21:
+        displayPixelLightSamples(1);
+        break;
+    case 22:
+        displayPixelLightSamples(2);
+        break;
+    case 23:
+        displayPixelLightSamples(8);
+        break;
+    }
+
+    frameCount ++;
+
+    return 1;
+}
diff --git a/java/Samples/src/com/android/samples/shader_def.rsh b/java/Samples/src/com/android/samples/shader_def.rsh
index 3f51785..1d804c6 100644
--- a/java/Samples/src/com/android/samples/shader_def.rsh
+++ b/java/Samples/src/com/android/samples/shader_def.rsh
@@ -39,6 +39,13 @@
     float light_CosinePower[2];
 } VertexShaderConstants2;
 
+typedef struct VertexShaderConstants3_s {
+    rs_matrix4x4 model;
+    rs_matrix4x4 proj;
+    float time;
+} VertexShaderConstants3;
+
+
 typedef struct FragentShaderConstants_s {
     float4 light0_DiffuseColor;
     float4 light0_SpecularColor;
@@ -52,6 +59,22 @@
     float4 light_SpecularColor[2];
 } FragentShaderConstants2;
 
+typedef struct FragentShaderConstants3_s {
+    float4 light0_DiffuseColor;
+    float4 light0_SpecularColor;
+    float4 light0_Posision;
+    float light0_Diffuse;
+    float light0_Specular;
+    float light0_CosinePower;
+
+    float4 light1_DiffuseColor;
+    float4 light1_SpecularColor;
+    float4 light1_Posision;
+    float light1_Diffuse;
+    float light1_Specular;
+    float light1_CosinePower;
+} FragentShaderConstants3;
+
 typedef struct VertexShaderInputs_s {
     float4 position;
     float3 normal;
diff --git a/java/tests/src/com/android/rs/test/RSTestCore.java b/java/tests/src/com/android/rs/test/RSTestCore.java
index c1f652f..265e1d6 100644
--- a/java/tests/src/com/android/rs/test/RSTestCore.java
+++ b/java/tests/src/com/android/rs/test/RSTestCore.java
@@ -16,6 +16,7 @@
 
 package com.android.rs.test;
 
+import android.content.Context;
 import android.content.res.Resources;
 import android.renderscript.*;
 import android.util.Log;
@@ -28,8 +29,10 @@
 public class RSTestCore {
     int mWidth;
     int mHeight;
+    Context mCtx;
 
-    public RSTestCore() {
+    public RSTestCore(Context ctx) {
+        mCtx = ctx;
     }
 
     private Resources mRes;
@@ -61,10 +64,10 @@
 
         unitTests = new ArrayList<UnitTest>();
 
-        unitTests.add(new UT_primitives(this, mRes));
-        unitTests.add(new UT_rsdebug(this, mRes));
-        unitTests.add(new UT_rstypes(this, mRes));
-        unitTests.add(new UT_fp_mad(this, mRes));
+        unitTests.add(new UT_primitives(this, mRes, mCtx));
+        unitTests.add(new UT_rsdebug(this, mRes, mCtx));
+        unitTests.add(new UT_rstypes(this, mRes, mCtx));
+        unitTests.add(new UT_fp_mad(this, mRes, mCtx));
         /*
         unitTests.add(new UnitTest(null, "<Pass>", 1));
         unitTests.add(new UnitTest());
diff --git a/java/tests/src/com/android/rs/test/RSTestView.java b/java/tests/src/com/android/rs/test/RSTestView.java
index 2f7542d..368f286 100644
--- a/java/tests/src/com/android/rs/test/RSTestView.java
+++ b/java/tests/src/com/android/rs/test/RSTestView.java
@@ -41,8 +41,11 @@
 
 public class RSTestView extends RSSurfaceView {
 
+    private Context mCtx;
+
     public RSTestView(Context context) {
         super(context);
+        mCtx = context;
         //setFocusable(true);
     }
 
@@ -55,7 +58,7 @@
             RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
             mRS = createRenderScriptGL(sc);
             mRS.setSurface(holder, w, h);
-            mRender = new RSTestCore();
+            mRender = new RSTestCore(mCtx);
             mRender.init(mRS, getResources(), w, h);
         }
     }
@@ -92,5 +95,3 @@
         return ret;
     }
 }
-
-
diff --git a/java/tests/src/com/android/rs/test/UT_fp_mad.java b/java/tests/src/com/android/rs/test/UT_fp_mad.java
index 409192b..f2c91af 100644
--- a/java/tests/src/com/android/rs/test/UT_fp_mad.java
+++ b/java/tests/src/com/android/rs/test/UT_fp_mad.java
@@ -16,19 +16,20 @@
 
 package com.android.rs.test;
 
+import android.content.Context;
 import android.content.res.Resources;
 import android.renderscript.*;
 
 public class UT_fp_mad extends UnitTest {
     private Resources mRes;
 
-    protected UT_fp_mad(RSTestCore rstc, Resources res) {
-        super(rstc, "Fp_Mad");
+    protected UT_fp_mad(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Fp_Mad", ctx);
         mRes = res;
     }
 
     public void run() {
-        RenderScript pRS = RenderScript.create();
+        RenderScript pRS = RenderScript.create(mCtx);
         ScriptC_fp_mad s = new ScriptC_fp_mad(pRS, mRes, R.raw.fp_mad);
         pRS.setMessageHandler(mRsMessage);
         s.invoke_fp_mad_test(0, 0);
@@ -37,4 +38,3 @@
         pRS.destroy();
     }
 }
-
diff --git a/java/tests/src/com/android/rs/test/UT_primitives.java b/java/tests/src/com/android/rs/test/UT_primitives.java
index 6e0859a..b7a65a5 100644
--- a/java/tests/src/com/android/rs/test/UT_primitives.java
+++ b/java/tests/src/com/android/rs/test/UT_primitives.java
@@ -16,14 +16,15 @@
 
 package com.android.rs.test;
 
+import android.content.Context;
 import android.content.res.Resources;
 import android.renderscript.*;
 
 public class UT_primitives extends UnitTest {
     private Resources mRes;
 
-    protected UT_primitives(RSTestCore rstc, Resources res) {
-        super(rstc, "Primitives");
+    protected UT_primitives(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Primitives", ctx);
         mRes = res;
     }
 
@@ -87,7 +88,7 @@
     }
 
     public void run() {
-        RenderScript pRS = RenderScript.create();
+        RenderScript pRS = RenderScript.create(mCtx);
         ScriptC_primitives s = new ScriptC_primitives(pRS, mRes, R.raw.primitives);
         pRS.setMessageHandler(mRsMessage);
         if (!initializeGlobals(s)) {
@@ -101,4 +102,3 @@
         pRS.destroy();
     }
 }
-
diff --git a/java/tests/src/com/android/rs/test/UT_rsdebug.java b/java/tests/src/com/android/rs/test/UT_rsdebug.java
index df31f98..0614b1a 100644
--- a/java/tests/src/com/android/rs/test/UT_rsdebug.java
+++ b/java/tests/src/com/android/rs/test/UT_rsdebug.java
@@ -16,19 +16,20 @@
 
 package com.android.rs.test;
 
+import android.content.Context;
 import android.content.res.Resources;
 import android.renderscript.*;
 
 public class UT_rsdebug extends UnitTest {
     private Resources mRes;
 
-    protected UT_rsdebug(RSTestCore rstc, Resources res) {
-        super(rstc, "rsDebug");
+    protected UT_rsdebug(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "rsDebug", ctx);
         mRes = res;
     }
 
     public void run() {
-        RenderScript pRS = RenderScript.create();
+        RenderScript pRS = RenderScript.create(mCtx);
         ScriptC_rsdebug s = new ScriptC_rsdebug(pRS, mRes, R.raw.rsdebug);
         pRS.setMessageHandler(mRsMessage);
         s.invoke_test_rsdebug(0, 0);
@@ -37,4 +38,3 @@
         pRS.destroy();
     }
 }
-
diff --git a/java/tests/src/com/android/rs/test/UT_rstypes.java b/java/tests/src/com/android/rs/test/UT_rstypes.java
index d1232ce..74211c8 100644
--- a/java/tests/src/com/android/rs/test/UT_rstypes.java
+++ b/java/tests/src/com/android/rs/test/UT_rstypes.java
@@ -16,19 +16,20 @@
 
 package com.android.rs.test;
 
+import android.content.Context;
 import android.content.res.Resources;
 import android.renderscript.*;
 
 public class UT_rstypes extends UnitTest {
     private Resources mRes;
 
-    protected UT_rstypes(RSTestCore rstc, Resources res) {
-        super(rstc, "rsTypes");
+    protected UT_rstypes(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "rsTypes", ctx);
         mRes = res;
     }
 
     public void run() {
-        RenderScript pRS = RenderScript.create();
+        RenderScript pRS = RenderScript.create(mCtx);
         ScriptC_rstypes s = new ScriptC_rstypes(pRS, mRes, R.raw.rstypes);
         pRS.setMessageHandler(mRsMessage);
         s.invoke_test_rstypes(0, 0);
@@ -37,4 +38,3 @@
         pRS.destroy();
     }
 }
-
diff --git a/java/tests/src/com/android/rs/test/UnitTest.java b/java/tests/src/com/android/rs/test/UnitTest.java
index 8923a19..a7722c7 100644
--- a/java/tests/src/com/android/rs/test/UnitTest.java
+++ b/java/tests/src/com/android/rs/test/UnitTest.java
@@ -15,6 +15,7 @@
  */
 
 package com.android.rs.test;
+import android.content.Context;
 import android.renderscript.RenderScript.RSMessageHandler;
 import android.util.Log;
 
@@ -24,6 +25,7 @@
     private ScriptField_ListAllocs_s.Item mItem;
     private RSTestCore mRSTC;
     private boolean msgHandled;
+    protected Context mCtx;
 
     /* These constants must match those in shared.rsh */
     public static final int RS_MSG_TEST_PASSED = 100;
@@ -32,25 +34,26 @@
     private static int numTests = 0;
     public int testID;
 
-    protected UnitTest(RSTestCore rstc, String n, int initResult) {
+    protected UnitTest(RSTestCore rstc, String n, int initResult, Context ctx) {
         super();
         mRSTC = rstc;
         name = n;
         msgHandled = false;
+        mCtx = ctx;
         result = initResult;
         testID = numTests++;
     }
 
-    protected UnitTest(RSTestCore rstc, String n) {
-        this(rstc, n, 0);
+    protected UnitTest(RSTestCore rstc, String n, Context ctx) {
+        this(rstc, n, 0, ctx);
     }
 
-    protected UnitTest(RSTestCore rstc) {
-        this (rstc, "<Unknown>");
+    protected UnitTest(RSTestCore rstc, Context ctx) {
+        this (rstc, "<Unknown>", ctx);
     }
 
-    protected UnitTest() {
-        this (null);
+    protected UnitTest(Context ctx) {
+        this (null, ctx);
     }
 
     protected RSMessageHandler mRsMessage = new RSMessageHandler() {
@@ -101,4 +104,3 @@
         }
     }
 }
-
diff --git a/rs.spec b/rs.spec
index 9f817b6..5daba08 100644
--- a/rs.spec
+++ b/rs.spec
@@ -322,6 +322,7 @@
 
 ScriptCCreate {
         param const char * resName
+        param const char * cacheDir
 	ret RsScript
 	}
 
diff --git a/rsContext.h b/rsContext.h
index 1dc9540..49ee676 100644
--- a/rsContext.h
+++ b/rsContext.h
@@ -207,6 +207,7 @@
     uint32_t getMaxFragmentTextures() const {return mGL.mMaxFragmentTextureImageUnits;}
     uint32_t getMaxFragmentUniformVectors() const {return mGL.mMaxFragmentUniformVectors;}
     uint32_t getMaxVertexUniformVectors() const {return mGL.mMaxVertexUniformVectors;}
+    uint32_t getMaxVertexAttributes() const {return mGL.mMaxVertexAttribs;}
 
     void launchThreads(WorkerCallback_t cbk, void *data);
     uint32_t getWorkerPoolSize() const {return (uint32_t)mWorkers.mCount;}
diff --git a/rsScriptC.cpp b/rsScriptC.cpp
index b3dbf11..507430d 100644
--- a/rsScriptC.cpp
+++ b/rsScriptC.cpp
@@ -402,7 +402,7 @@
 extern const char rs_runtime_lib_bc[];
 extern unsigned rs_runtime_lib_bc_size;
 
-void ScriptCState::runCompiler(Context *rsc, ScriptC *s, const char *resName) {
+void ScriptCState::runCompiler(Context *rsc, ScriptC *s, const char *resName, const char *cacheDir) {
     {
         s->mBccScript = bccCreateScript();
         s->mEnviroment.mIsThreadable = true;
@@ -413,7 +413,8 @@
         if (bccReadBC(s->mBccScript,
                       s->mEnviroment.mScriptText,
                       s->mEnviroment.mScriptTextLength,
-                      resName) >= 0) {
+                      resName,
+                      cacheDir) >= 0) {
           //bccLinkBC(s->mBccScript, rs_runtime_lib_bc, rs_runtime_lib_bc_size);
           bccCompileBC(s->mBccScript);
         } else {
@@ -534,7 +535,7 @@
     ss->mScript->mEnviroment.mScriptTextLength = len;
 }
 
-RsScript rsi_ScriptCCreate(Context * rsc, const char *resName)
+RsScript rsi_ScriptCCreate(Context * rsc, const char *resName, const char *cacheDir)
 {
     ScriptCState *ss = &rsc->mScriptC;
 
@@ -542,7 +543,7 @@
     ss->mScript.clear();
     s->incUserRef();
 
-    ss->runCompiler(rsc, s.get(), resName);
+    ss->runCompiler(rsc, s.get(), resName, cacheDir);
     ss->clear(rsc);
     return s.get();
 }
diff --git a/rsScriptC.h b/rsScriptC.h
index ab2db5c..a714132 100644
--- a/rsScriptC.h
+++ b/rsScriptC.h
@@ -83,7 +83,7 @@
     void init(Context *rsc);
 
     void clear(Context *rsc);
-    void runCompiler(Context *rsc, ScriptC *s, const char *resName);
+    void runCompiler(Context *rsc, ScriptC *s, const char *resName, const char *cacheDir);
 
     struct SymbolTable_t {
         const char * mName;
diff --git a/rsVertexArray.cpp b/rsVertexArray.cpp
index 8a9fafe..d9393fe 100644
--- a/rsVertexArray.cpp
+++ b/rsVertexArray.cpp
@@ -81,8 +81,12 @@
                            class VertexArrayState *state,
                            ShaderCache *sc) const {
     rsc->checkError("VertexArray::setupGL2 start");
-    for (uint32_t ct=1; ct <= state->mLastEnableCount; ct++) {
-        glDisableVertexAttribArray(ct);
+    uint32_t maxAttrs = state->mAttrsEnabledSize;
+    for (uint32_t ct=1; ct < maxAttrs; ct++) {
+        if(state->mAttrsEnabled[ct]) {
+            glDisableVertexAttribArray(ct);
+            state->mAttrsEnabled[ct] = false;
+        }
     }
 
     rsc->checkError("VertexArray::setupGL2 disabled");
@@ -91,10 +95,11 @@
         if (rsc->props.mLogShadersAttr) {
             logAttrib(ct, slot);
         }
-        if (slot < 0) {
+        if (slot < 0 || slot >= (int32_t)maxAttrs) {
             continue;
         }
         glEnableVertexAttribArray(slot);
+        state->mAttrsEnabled[slot] = true;
         glBindBuffer(GL_ARRAY_BUFFER, mAttribs[ct].buffer);
         glVertexAttribPointer(slot,
                               mAttribs[ct].size,
@@ -103,12 +108,25 @@
                               mAttribs[ct].stride,
                               mAttribs[ct].ptr + mAttribs[ct].offset);
     }
-    state->mLastEnableCount = mCount;
     rsc->checkError("VertexArray::setupGL2 done");
 }
 ////////////////////////////////////////////
+VertexArrayState::VertexArrayState() {
+    mAttrsEnabled = NULL;
+    mAttrsEnabledSize = 0;
+}
 
-void VertexArrayState::init(Context *) {
-    mLastEnableCount = 0;
+VertexArrayState::~VertexArrayState() {
+    if (mAttrsEnabled) {
+        delete[] mAttrsEnabled;
+        mAttrsEnabled = NULL;
+    }
+}
+void VertexArrayState::init(Context *rsc) {
+    mAttrsEnabledSize = rsc->getMaxVertexAttributes();
+    mAttrsEnabled = new bool[mAttrsEnabledSize];
+    for (uint32_t ct = 0; ct < mAttrsEnabledSize; ct++) {
+        mAttrsEnabled[ct] = false;
+    }
 }
 
diff --git a/rsVertexArray.h b/rsVertexArray.h
index 7bcfa68..45d9e82 100644
--- a/rsVertexArray.h
+++ b/rsVertexArray.h
@@ -63,9 +63,12 @@
 
 class VertexArrayState {
 public:
+    VertexArrayState();
+    ~VertexArrayState();
     void init(Context *);
 
-    uint32_t mLastEnableCount;
+    bool *mAttrsEnabled;
+    uint32_t mAttrsEnabledSize;
 };