checkpoint filmstrip, implemented TLS.
diff --git a/libs/rs/RenderScriptEnv.h b/libs/rs/RenderScriptEnv.h
index fff96eb..221ab41 100644
--- a/libs/rs/RenderScriptEnv.h
+++ b/libs/rs/RenderScriptEnv.h
@@ -30,64 +30,64 @@
 #define RS_PROGRAM_VERTEX_TEXTURE_OFFSET 32
 
 typedef struct {
-    const void * (*loadEnvVp)(void *con, uint32_t bank, uint32_t offset);
+    const void * (*loadEnvVp)(uint32_t bank, uint32_t offset);
 
-    float (*loadEnvF)(void *con, uint32_t bank, uint32_t offset);
-    int32_t (*loadEnvI32)(void *con, uint32_t bank, uint32_t offset);
-    uint32_t (*loadEnvU32)(void *con, uint32_t bank, uint32_t offset);
-    void (*loadEnvVec4)(void *con, uint32_t bank, uint32_t offset, rsc_Vector4 *);
-    void (*loadEnvMatrix)(void *con, uint32_t bank, uint32_t offset, rsc_Matrix *);
+    float (*loadEnvF)(uint32_t bank, uint32_t offset);
+    int32_t (*loadEnvI32)(uint32_t bank, uint32_t offset);
+    uint32_t (*loadEnvU32)(uint32_t bank, uint32_t offset);
+    void (*loadEnvVec4)(uint32_t bank, uint32_t offset, rsc_Vector4 *);
+    void (*loadEnvMatrix)(uint32_t bank, uint32_t offset, rsc_Matrix *);
 
-    void (*storeEnvF)(void *con, uint32_t bank, uint32_t offset, float);
-    void (*storeEnvI32)(void *con, uint32_t bank, uint32_t offset, int32_t);
-    void (*storeEnvU32)(void *con, uint32_t bank, uint32_t offset, uint32_t);
-    void (*storeEnvVec4)(void *con, uint32_t bank, uint32_t offset, const rsc_Vector4 *);
-    void (*storeEnvMatrix)(void *con, uint32_t bank, uint32_t offset, const rsc_Matrix *);
+    void (*storeEnvF)(uint32_t bank, uint32_t offset, float);
+    void (*storeEnvI32)(uint32_t bank, uint32_t offset, int32_t);
+    void (*storeEnvU32)(uint32_t bank, uint32_t offset, uint32_t);
+    void (*storeEnvVec4)(uint32_t bank, uint32_t offset, const rsc_Vector4 *);
+    void (*storeEnvMatrix)(uint32_t bank, uint32_t offset, const rsc_Matrix *);
 
-    void (*matrixLoadIdentity)(void *con, rsc_Matrix *);
-    void (*matrixLoadFloat)(void *con, rsc_Matrix *, const float *);
-    void (*matrixLoadMat)(void *con, rsc_Matrix *, const rsc_Matrix *);
-    void (*matrixLoadRotate)(void *con, rsc_Matrix *, float rot, float x, float y, float z);
-    void (*matrixLoadScale)(void *con, rsc_Matrix *, float x, float y, float z);
-    void (*matrixLoadTranslate)(void *con, rsc_Matrix *, float x, float y, float z);
-    void (*matrixLoadMultiply)(void *con, rsc_Matrix *, const rsc_Matrix *lhs, const rsc_Matrix *rhs);
-    void (*matrixMultiply)(void *con, rsc_Matrix *, const rsc_Matrix *rhs);
-    void (*matrixRotate)(void *con, rsc_Matrix *, float rot, float x, float y, float z);
-    void (*matrixScale)(void *con, rsc_Matrix *, float x, float y, float z);
-    void (*matrixTranslate)(void *con, rsc_Matrix *, float x, float y, float z);
+    void (*matrixLoadIdentity)(rsc_Matrix *);
+    void (*matrixLoadFloat)(rsc_Matrix *, const float *);
+    void (*matrixLoadMat)(rsc_Matrix *, const rsc_Matrix *);
+    void (*matrixLoadRotate)(rsc_Matrix *, float rot, float x, float y, float z);
+    void (*matrixLoadScale)(rsc_Matrix *, float x, float y, float z);
+    void (*matrixLoadTranslate)(rsc_Matrix *, float x, float y, float z);
+    void (*matrixLoadMultiply)(rsc_Matrix *, const rsc_Matrix *lhs, const rsc_Matrix *rhs);
+    void (*matrixMultiply)(rsc_Matrix *, const rsc_Matrix *rhs);
+    void (*matrixRotate)(rsc_Matrix *, float rot, float x, float y, float z);
+    void (*matrixScale)(rsc_Matrix *, float x, float y, float z);
+    void (*matrixTranslate)(rsc_Matrix *, float x, float y, float z);
 
-    void (*color)(void *con, float r, float g, float b, float a);
+    void (*color)(float r, float g, float b, float a);
 
-    void (*programFragmentBindTexture)(void *con, RsProgramFragment, uint32_t slot, RsAllocation);
-    void (*programFragmentBindSampler)(void *con, RsProgramFragment, uint32_t slot, RsAllocation);
+    void (*programFragmentBindTexture)(RsProgramFragment, uint32_t slot, RsAllocation);
+    void (*programFragmentBindSampler)(RsProgramFragment, uint32_t slot, RsAllocation);
 
-    void (*materialDiffuse)(void *con, float r, float g, float b, float a);
-    void (*materialSpecular)(void *con, float r, float g, float b, float a);
-    void (*lightPosition)(void *con, float x, float y, float z, float w);
-    void (*materialShininess)(void *con, float s);
+    void (*materialDiffuse)(float r, float g, float b, float a);
+    void (*materialSpecular)(float r, float g, float b, float a);
+    void (*lightPosition)(float x, float y, float z, float w);
+    void (*materialShininess)(float s);
 
-    void (*uploadToTexture)(void *con, RsAllocation va, uint32_t baseMipLevel);
+    void (*uploadToTexture)(RsAllocation va, uint32_t baseMipLevel);
 
-    void (*enable)(void *con, uint32_t);
-    void (*disable)(void *con, uint32_t);
+    void (*enable)(uint32_t);
+    void (*disable)(uint32_t);
 
-    uint32_t (*rand)(void *con, uint32_t max);
+    uint32_t (*rand)(uint32_t max);
 
-    void (*contextBindProgramFragment)(void *con, RsProgramFragment pf);
-    void (*contextBindProgramFragmentStore)(void *con, RsProgramFragmentStore pfs);
+    void (*contextBindProgramFragment)(RsProgramFragment pf);
+    void (*contextBindProgramFragmentStore)(RsProgramFragmentStore pfs);
 
 
     // Drawing funcs
-    void (*renderTriangleMesh)(void *con, RsTriangleMesh);
-    void (*renderTriangleMeshRange)(void *con, RsTriangleMesh, uint32_t start, uint32_t count);
+    void (*renderTriangleMesh)(RsTriangleMesh);
+    void (*renderTriangleMeshRange)(RsTriangleMesh, uint32_t start, uint32_t count);
 
     // Assumes (GL_FIXED) x,y,z (GL_UNSIGNED_BYTE)r,g,b,a
-    void (*drawTriangleArray)(void *con, RsAllocation alloc, uint32_t count);
+    void (*drawTriangleArray)(RsAllocation alloc, uint32_t count);
 
-    void (*drawRect)(void *con, int32_t x1, int32_t x2, int32_t y1, int32_t y2);
+    void (*drawRect)(int32_t x1, int32_t x2, int32_t y1, int32_t y2);
 } rsc_FunctionTable;
 
-typedef int (*rsc_RunScript)(void *con, const rsc_FunctionTable *, uint32_t launchIndex);
+typedef int (*rsc_RunScript)(uint32_t launchIndex, const rsc_FunctionTable *);
 
 
 /* EnableCap */
diff --git a/libs/rs/java/Film/Android.mk b/libs/rs/java/Film/Android.mk
new file mode 100644
index 0000000..2e9c243
--- /dev/null
+++ b/libs/rs/java/Film/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
+
+LOCAL_PACKAGE_NAME := Film
+
+include $(BUILD_PACKAGE)
diff --git a/libs/rs/java/Film/AndroidManifest.xml b/libs/rs/java/Film/AndroidManifest.xml
new file mode 100644
index 0000000..491ee14
--- /dev/null
+++ b/libs/rs/java/Film/AndroidManifest.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.film">
+    <application android:label="Film">
+        <activity android:name="Film"
+                  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/libs/rs/java/Film/res/raw/filmimage.c b/libs/rs/java/Film/res/raw/filmimage.c
new file mode 100644
index 0000000..3bd9496
--- /dev/null
+++ b/libs/rs/java/Film/res/raw/filmimage.c
@@ -0,0 +1,110 @@
+// Fountain test script
+
+#pragma version(1)
+#pragma stateVertex(orthoWindow)
+#pragma stateRaster(flat)
+#pragma stateFragment(PgmFragBackground)
+#pragma stateFragmentStore(MyBlend)
+
+
+int main(void* con, int ft, int launchID) {
+    int count, touch, x, y, rate, maxLife, lifeShift;
+    int life;
+    int ct, ct2;
+    int newPart;
+    int drawCount;
+    int dx, dy, idx;
+    int posx,posy;
+    int c;
+    int srcIdx;
+    int dstIdx;
+
+    count = loadI32(con, 0, 1);
+    touch = loadI32(con, 0, 2);
+    x = loadI32(con, 0, 3);
+    y = loadI32(con, 0, 4);
+
+    rate = 4;
+    maxLife = (count / rate) - 1;
+    lifeShift = 0;
+    {
+        life = maxLife;
+        while (life > 255) {
+            life = life >> 1;
+            lifeShift ++;
+        }
+    }
+
+    drawRect(con, 0, 256, 0, 512);
+    contextBindProgramFragment(con, NAMED_PgmFragParts);
+
+    if (touch) {
+        newPart = loadI32(con, 2, 0);
+        for (ct2=0; ct2<rate; ct2++) {
+            dx = scriptRand(con, 0x10000) - 0x8000;
+            dy = scriptRand(con, 0x10000) - 0x8000;
+
+            idx = newPart * 5 + 1;
+            storeI32(con, 2, idx, dx);
+            storeI32(con, 2, idx + 1, dy);
+            storeI32(con, 2, idx + 2, maxLife);
+            storeI32(con, 2, idx + 3, x << 16);
+            storeI32(con, 2, idx + 4, y << 16);
+
+            newPart++;
+            if (newPart >= count) {
+                newPart = 0;
+            }
+        }
+        storeI32(con, 2, 0, newPart);
+    }
+
+    drawCount = 0;
+    for (ct=0; ct < count; ct++) {
+        srcIdx = ct * 5 + 1;
+
+        dx = loadI32(con, 2, srcIdx);
+        dy = loadI32(con, 2, srcIdx + 1);
+        life = loadI32(con, 2, srcIdx + 2);
+        posx = loadI32(con, 2, srcIdx + 3);
+        posy = loadI32(con, 2, srcIdx + 4);
+
+        if (life) {
+            if (posy < (480 << 16)) {
+                dstIdx = drawCount * 9;
+                c = 0xffafcf | ((life >> lifeShift) << 24);
+
+                storeU32(con, 1, dstIdx, c);
+                storeI32(con, 1, dstIdx + 1, posx);
+                storeI32(con, 1, dstIdx + 2, posy);
+
+                storeU32(con, 1, dstIdx + 3, c);
+                storeI32(con, 1, dstIdx + 4, posx + 0x10000);
+                storeI32(con, 1, dstIdx + 5, posy + dy * 4);
+
+                storeU32(con, 1, dstIdx + 6, c);
+                storeI32(con, 1, dstIdx + 7, posx - 0x10000);
+                storeI32(con, 1, dstIdx + 8, posy + dy * 4);
+                drawCount ++;
+            } else {
+                if (dy > 0) {
+                    dy = (-dy) >> 1;
+                }
+            }
+
+            posx = posx + dx;
+            posy = posy + dy;
+            dy = dy + 0x400;
+            life --;
+
+            //storeI32(con, 2, srcIdx, dx);
+            storeI32(con, 2, srcIdx + 1, dy);
+            storeI32(con, 2, srcIdx + 2, life);
+            storeI32(con, 2, srcIdx + 3, posx);
+            storeI32(con, 2, srcIdx + 4, posy);
+        }
+    }
+
+    drawTriangleArray(con, NAMED_PartBuffer, drawCount);
+    return 1;
+}
diff --git a/libs/rs/java/Film/res/raw/filmstrip.c b/libs/rs/java/Film/res/raw/filmstrip.c
new file mode 100644
index 0000000..75810c0
--- /dev/null
+++ b/libs/rs/java/Film/res/raw/filmstrip.c
@@ -0,0 +1,131 @@
+// Fountain test script
+
+#pragma version(1)
+#pragma stateVertex(PV)
+#pragma stateFragment(default)
+#pragma stateFragmentStore(default)
+
+/*
+typedef struct FilmScriptUserEnvRec {
+    RsAllocation tex[13];
+    int32_t triangleOffsets[64];
+    float triangleOffsetsTex[64];
+    int32_t triangleOffsetsCount;
+} FilmScriptUserEnv; 
+*/ 
+
+// The script enviroment has 3 env allocations.
+// bank0: (r) The enviroment structure
+// bank1: (r) The position information
+// bank2: (rw) The temporary texture state
+
+int main(void* con, int ft, int index) 
+{
+    int f1;
+    int f2;
+    int f3;
+    int f4;
+    int f5;
+    int f6;
+    int f7;
+    int f8;
+    int f9;
+    int f10;
+    int f11;
+    int f12;
+    int f13;
+    int f14;
+    int f15;
+    int f16;
+
+    int trans;  // float
+    int rot;   // float
+
+
+    //trans = loadEnvF(con, 1, 0);
+    //rot = loadEnvF(con, 1, 1);
+
+    //matrixLoadTranslate(con, &f1, 0, 0, trans);
+    //matrixRotate(con, &f1, rot, 1, 0, 0);
+    //matrixScale(con, &f1, 3.0f, 3.0f, 3.0f);
+    //storeEnvMatrix(con, 3, RS_PROGRAM_VERTEX_MODELVIEW_OFFSET, &f1);
+
+    //rsc_Matrix m;
+    //int imgId = 0;
+
+    // This should be replaced in the compiler with a 
+    // smart load of a structure.
+    //const FilmScriptUserEnv *env = loadEnvVp(con, 0,0);
+
+    //materialDiffuse(con, 0.0f, 0.0f, 0.0f, 1.0f);
+    //materialSpecular(con, 0.5f, 0.5f, 0.5f, 0.5f);
+    //materialShininess(con, 20.0f);
+
+
+
+    //lightPosition(con, 0.2f, -0.2f, -2.0f, 0.0f);
+
+    //contextBindProgramFragmentStore(con, NAMED_PFSBackground);
+    //contextBindProgramFragment(con, NAMED_PFBackground);
+    //enable(con, GL_LIGHTING);
+    renderTriangleMesh(con, NAMED_mesh);
+
+/*
+    contextBindProgramFragmentStore(con, env->fsImages);
+    contextBindProgramFragment(con, env->fpImages);
+    disable(con, GL_LIGHTING);
+
+    float focusPos = loadEnvF(con, 1, 2);
+    int32_t focusID = 0;
+    int32_t lastFocusID = loadEnvI32(con, 2, 0);
+    int32_t imgCount = 13;
+
+    if (trans > (-.3)) {
+        focusID = -1.0 - focusPos;
+        if (focusID >= imgCount) {
+            focusID = -1;
+        }
+    } else {
+        focusID = -1;
+    }
+
+    if (focusID != lastFocusID) {
+        if (lastFocusID >= 0) {
+            uploadToTexture(con, env->tex[lastFocusID], 1);
+        }
+        if (focusID >= 0) {
+            uploadToTexture(con, env->tex[focusID], 0);
+        }
+    }
+    storeEnvI32(con, 2, 0, focusID);
+
+
+    for (imgId=1; imgId <= imgCount; imgId++) {
+        float pos = focusPos + imgId + .4f;
+        int offset = (int)floor(pos*2);
+        pos -= 0.75;
+    
+        offset += env->triangleOffsetsCount / 2;
+    
+        if ((offset < 0) || (offset >= env->triangleOffsetsCount)) {
+            continue;
+        }
+    
+        int start = offset -2;
+        int end = offset + 2;
+    
+        if (start < 0) {
+            start = 0;
+        }
+        if (end > env->triangleOffsetsCount) {
+            end = env->triangleOffsetsCount;
+        }
+    
+        programFragmentBindTexture(con, env->fpImages, 0, env->tex[imgId - 1]);
+        matrixLoadTranslate(con, &m, -pos - env->triangleOffsetsTex[env->triangleOffsetsCount / 2], 0, 0); 
+        storeEnvMatrix(con, 3, RS_PROGRAM_VERTEX_TEXTURE_OFFSET, &m);
+        renderTriangleMeshRange(con, env->mesh, env->triangleOffsets[start], env->triangleOffsets[end] - env->triangleOffsets[start]);
+    } 
+*/
+}
+
diff --git a/libs/rs/java/Film/src/com/android/film/Film.java b/libs/rs/java/Film/src/com/android/film/Film.java
new file mode 100644
index 0000000..6e99816
--- /dev/null
+++ b/libs/rs/java/Film/src/com/android/film/Film.java
@@ -0,0 +1,90 @@
+/*
+ * 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.film;
+
+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 Film extends Activity {
+    //EventListener mListener = new EventListener();
+
+    private static final String LOG_TAG = "libRS_jni";
+    private static final boolean DEBUG  = false;
+    private static final boolean LOG_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;
+
+    private FilmView mView;
+
+    // get the current looper (from your Activity UI thread for instance
+
+
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        // Create our Preview view and set it as the content of our
+        // Activity
+        mView = new FilmView(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.onResume();
+    }
+
+    @Override
+    protected void onPause() {
+        // Ideally a game should implement onResume() and onPause()
+        // to take appropriate action when the activity looses focus
+        super.onPause();
+        mView.onPause();
+
+        Runtime.getRuntime().exit(0);
+    }
+
+
+    static void log(String message) {
+        if (LOG_ENABLED) {
+            Log.v(LOG_TAG, message);
+        }
+    }
+
+
+}
+
diff --git a/libs/rs/java/Film/src/com/android/film/FilmRS.java b/libs/rs/java/Film/src/com/android/film/FilmRS.java
new file mode 100644
index 0000000..b4b5f4b
--- /dev/null
+++ b/libs/rs/java/Film/src/com/android/film/FilmRS.java
@@ -0,0 +1,242 @@
+/*
+ * 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.film;
+
+import java.io.Writer;
+
+import android.renderscript.RenderScript;
+import android.renderscript.ProgramVertexAlloc;
+import android.renderscript.Matrix;
+
+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 FilmRS {
+
+    public FilmRS() {
+    }
+
+    public void init(RenderScript rs, Resources res, int width, int height) {
+        mRS = rs;
+        mRes = res;
+        initNamed();
+        initRS();
+    }
+
+    public void setFilmStripPosition(int x, int y)
+    {
+        if (x < 0) {
+            x = 0;
+        }
+        if (x > 50) {
+            x = 50;
+        }
+    
+        float anim = ((float)x) / 50.f;
+        mBufferPos[0] = -2f * anim - .2f;   // translation
+        mBufferPos[1] = -90 + (anim * 40);  // rotation
+        mBufferPos[2] = ((float)y) / 16.f - 8;  // focusPos
+    
+        mAllocPos.data(mBufferPos);
+    }
+
+
+    private Resources mRes;
+    private RenderScript mRS;
+    private RenderScript.Script mScriptStrip;
+    private RenderScript.Script mScriptImage;
+    private RenderScript.Element mElementVertex;
+    private RenderScript.Element mElementIndex;
+    private RenderScript.Sampler mSampler;
+    private RenderScript.ProgramFragmentStore mPFSBackground;
+    private RenderScript.ProgramFragmentStore mPFSImages;
+    private RenderScript.ProgramFragment mPFBackground;
+    private RenderScript.ProgramFragment mPFImages;
+    private RenderScript.ProgramVertex mPV;
+    private ProgramVertexAlloc mPVA;
+
+    private RenderScript.Allocation mAllocEnv;
+    private RenderScript.Allocation mAllocPos;
+    private RenderScript.Allocation mAllocState;
+    private RenderScript.Allocation mAllocPV;
+    private RenderScript.TriangleMesh mMesh;
+
+    private float[] mBufferPos;
+    private float[] mBufferPV;
+
+    private void initNamed() {
+        mElementVertex = mRS.elementGetPredefined(
+            RenderScript.ElementPredefined.NORM_ST_XYZ_F32);
+        mElementIndex = mRS.elementGetPredefined(
+            RenderScript.ElementPredefined.INDEX_16);
+
+        mRS.triangleMeshBegin(mElementVertex, mElementIndex);
+        FilmStripMesh fsm = new FilmStripMesh();
+        fsm.init(mRS);
+        mMesh = mRS.triangleMeshCreate();
+        mMesh.setName("mesh");
+        Log.e("rs", "Done loading strips");
+
+
+        mRS.samplerBegin();
+        mRS.samplerSet(RenderScript.SamplerParam.FILTER_MIN,
+                       RenderScript.SamplerValue.LINEAR_MIP_LINEAR);
+        mRS.samplerSet(RenderScript.SamplerParam.WRAP_MODE_S,
+                       RenderScript.SamplerValue.CLAMP);
+        mRS.samplerSet(RenderScript.SamplerParam.WRAP_MODE_T,
+                       RenderScript.SamplerValue.CLAMP);
+        mSampler = mRS.samplerCreate();
+
+        mRS.programFragmentBegin(null, null);
+        mPFBackground = mRS.programFragmentCreate();
+        mPFBackground.setName("PFBackground");
+
+        mRS.programFragmentBegin(null, null);
+        mRS.programFragmentSetTexEnable(0, true);
+        //mRS.programFragmentSetEnvMode(0, RS_TEX_ENV_MODE_REPLACE);
+        //rsProgramFragmentSetType(0, gEnv.tex[0]->getType());
+        mPFImages = mRS.programFragmentCreate();
+        mPFImages.setName("PFImages");
+        mPFImages.bindSampler(mSampler, 0);
+
+        mRS.programFragmentStoreBegin(null, null);
+        mRS.programFragmentStoreDepthFunc(RenderScript.DepthFunc.LESS);
+        mRS.programFragmentStoreDitherEnable(true);
+        mPFSBackground = mRS.programFragmentStoreCreate();
+        mPFSBackground.setName("PFSBackground");
+
+        mRS.programFragmentStoreBegin(null, null);
+        mRS.programFragmentStoreDepthFunc(RenderScript.DepthFunc.EQUAL);
+        mRS.programFragmentStoreDitherEnable(false);
+        mRS.programFragmentStoreDepthMask(false);
+        mRS.programFragmentStoreBlendFunc(RenderScript.BlendSrcFunc.ONE, 
+                                          RenderScript.BlendDstFunc.ONE);
+        mPFSImages = mRS.programFragmentStoreCreate();
+        mPFSImages.setName("PFSImages");
+
+        mRS.programVertexBegin(null, null);
+        mRS.programVertexSetTextureMatrixEnable(true);
+        mPV = mRS.programVertexCreate();
+        mPV.setName("PV");
+
+        Log.e("rs", "Done loading named");
+    }
+
+
+    private Bitmap mBackground;
+
+    int mParams[] = new int[10];
+
+    private void initRS() {
+        int partCount = 1024;
+
+        mRS.scriptCBegin();
+        mRS.scriptCSetClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+        mRS.scriptCSetScript(mRes, R.raw.filmstrip);
+        mRS.scriptCSetRoot(true);
+        mScriptStrip = mRS.scriptCCreate();
+
+        mBufferPos = new float[3];
+        mAllocPos = mRS.allocationCreatePredefSized(
+            RenderScript.ElementPredefined.USER_FLOAT, 
+            mBufferPos.length);
+        setFilmStripPosition(0, 0);
+
+        mPVA = new ProgramVertexAlloc(mRS);
+        mPV.bindAllocation(0, mPVA.mAlloc);
+        mPVA.setupProjectionNormalized(320, 480);
+
+        Matrix m = new Matrix();
+
+        m.loadIdentity();
+
+        m.translate(0, 0, 1);
+        m.rotate(90, 0, 0, 1);
+        m.rotate(20, 1, 0, 0);
+        mPVA.loadModelview(m);
+
+
+
+
+
+        //mScriptStrip.bindAllocation(mEnvAlloc, 0);
+        mScriptStrip.bindAllocation(mAllocPos, 1);
+        //mScriptStrip.bindAllocation(gStateAlloc, 2);
+        mScriptStrip.bindAllocation(mPVA.mAlloc, 3);
+
+
+        //mIntAlloc = mRS.allocationCreatePredefSized(RenderScript.ElementPredefined.USER_I32, 10);
+        //mPartAlloc = mRS.allocationCreatePredefSized(RenderScript.ElementPredefined.USER_I32, partCount * 3 * 3);
+        //mPartAlloc.setName("PartBuffer");
+        //mVertAlloc = mRS.allocationCreatePredefSized(RenderScript.ElementPredefined.USER_I32, partCount * 5 + 1);
+/*
+        {
+            Resources res = getResources();
+            Drawable d = res.getDrawable(R.drawable.gadgets_clock_mp3);
+            BitmapDrawable bd = (BitmapDrawable)d;
+            Bitmap b = bd.getBitmap();
+            mTexture = mRS.allocationCreateFromBitmap(b,
+                                                      RenderScript.ElementPredefined.RGB_565,
+                                                      true);
+            mTexture.uploadToTexture(0);
+        }
+
+        mRS.programFragmentStoreBegin(null, null);
+        mRS.programFragmentStoreBlendFunc(RenderScript.BlendSrcFunc.SRC_ALPHA, RenderScript.BlendDstFunc.ONE);
+        mRS.programFragmentStoreDepthFunc(RenderScript.DepthFunc.ALWAYS);
+        mPFS = mRS.programFragmentStoreCreate();
+        mPFS.setName("MyBlend");
+        mRS.contextBindProgramFragmentStore(mPFS);
+
+        mRS.samplerBegin();
+        mRS.samplerSet(RenderScript.SamplerParam.FILTER_MAG, RenderScript.SamplerValue.LINEAR);
+        mRS.samplerSet(RenderScript.SamplerParam.FILTER_MIN, RenderScript.SamplerValue.LINEAR);
+        mSampler = mRS.samplerCreate();
+
+
+        mParams[0] = 0;
+        mParams[1] = partCount;
+        mParams[2] = 0;
+        mParams[3] = 0;
+        mParams[4] = 0;
+        mIntAlloc.data(mParams);
+
+        int t2[] = new int[partCount * 4*3];
+        for (int ct=0; ct < t2.length; ct++) {
+            t2[ct] = 0;
+        }
+        mPartAlloc.data(t2);
+        */
+
+        mRS.contextBindRootScript(mScriptStrip);
+    }
+}
+
+
+
diff --git a/libs/rs/java/Film/src/com/android/film/FilmStripMesh.java b/libs/rs/java/Film/src/com/android/film/FilmStripMesh.java
new file mode 100644
index 0000000..02bffd8
--- /dev/null
+++ b/libs/rs/java/Film/src/com/android/film/FilmStripMesh.java
@@ -0,0 +1,255 @@
+/*
+ * 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.
+ */
+
+
+package com.android.film;
+
+import java.io.Writer;
+import java.lang.Math;
+import android.util.Log;
+
+import android.renderscript.RenderScript;
+
+
+class FilmStripMesh {
+
+    class Vertex {
+        float nx;
+        float ny;
+        float nz;
+        float s;
+        float t;
+        float x;
+        float y;
+        float z;
+
+        Vertex() {
+            nx = 0;
+            ny = 0;
+            nz = 0;
+            s = 0;
+            t = 0;
+            x = 0;
+            y = 0;
+            z = 0;
+        }
+
+        void xyz(float _x, float _y, float _z) {
+            x = _x;
+            y = _y;
+            z = _z;
+        }
+
+        void nxyz(float _x, float _y, float _z) {
+            nx = _x;
+            ny = _y;
+            nz = _z;
+        }
+
+        void st(float _s, float _t) {
+            s = _s;
+            t = _t;
+        }
+
+        void computeNorm(Vertex v1, Vertex v2) {
+            float dx = v1.x - v2.x;
+            float dy = v1.y - v2.y;
+            float dz = v1.z - v2.z;
+            float len = (float)java.lang.Math.sqrt(dx*dx + dy*dy + dz*dz);
+            dx /= len;
+            dy /= len;
+            dz /= len;
+        
+            nx = dx * dz;
+            ny = dy * dz;
+            nz = (float)java.lang.Math.sqrt(dx*dx + dy*dy);
+        
+            len = (float)java.lang.Math.sqrt(nx*nx + ny*ny + nz*nz);
+            nx /= len;
+            ny /= len;
+            nz /= len;
+        }
+
+        void addToRS(RenderScript rs) {
+            rs.triangleMeshAddVertex_XYZ_ST_NORM(x, y, z, s, t, nx, ny, nz);
+        }
+    }
+
+    int[] mTriangleOffsets;
+    float[] mTriangleOffsetsTex;
+    int mTriangleOffsetsCount;
+
+    void init(RenderScript rs)
+    {
+        float vtx[] = new float[] {
+            60.431003f, 124.482050f,
+            60.862074f, 120.872604f,
+            61.705303f, 117.336662f,
+            62.949505f, 113.921127f,
+            64.578177f, 110.671304f,
+            66.569716f, 107.630302f,
+            68.897703f, 104.838457f,
+            71.531259f, 102.332803f,
+            74.435452f, 100.146577f,
+            77.571757f, 98.308777f,
+            80.898574f, 96.843781f,
+            84.371773f, 95.771023f,
+            87.945283f, 95.104731f,
+            98.958994f, 95.267098f,
+            109.489523f, 98.497596f,
+            118.699582f, 104.539366f,
+            125.856872f, 112.912022f,
+            130.392311f, 122.949849f,
+            131.945283f, 133.854731f,
+            130.392311f, 144.759613f,
+            125.856872f, 154.797439f,
+            118.699582f, 163.170096f,
+            109.489523f, 169.211866f,
+            98.958994f, 172.442364f,
+            87.945283f, 172.604731f,
+            72.507313f, 172.672927f,
+            57.678920f, 168.377071f,
+            44.668135f, 160.067134f,
+            34.534908f, 148.420104f,
+            28.104767f, 134.384831f,
+            25.901557f, 119.104731f,
+            28.104767f, 103.824631f,
+            34.534908f, 89.789358f,
+            44.668135f, 78.142327f,
+            57.678920f, 69.832390f,
+            72.507313f, 65.536534f,
+            87.945283f, 65.604731f,
+            106.918117f, 65.688542f,
+            125.141795f, 60.409056f,
+            141.131686f, 50.196376f,
+            153.585137f, 35.882502f,
+            161.487600f, 18.633545f,
+            164.195283f, -0.145269f,
+            161.487600f, -18.924084f,
+            153.585137f, -36.173040f,
+            141.131686f, -50.486914f,
+            125.141795f, -60.699594f,
+            106.918117f, -65.979081f,
+            87.945283f, -65.895269f,
+            80f, -65.895269f,
+            60f, -65.895269f,
+            40f, -65.895269f,
+            20f, -65.895269f,
+            0f, -65.895269f,
+            -20f, -65.895269f,
+            -40f, -65.895269f,
+            -60f, -65.895269f,
+            -80f, -65.895269f,
+            -87.945283f, -65.895269f,
+            -106.918117f, -65.979081f,
+            -125.141795f, -60.699594f,
+            -141.131686f, -50.486914f,
+            -153.585137f, -36.173040f,
+            -161.487600f, -18.924084f,
+            -164.195283f, -0.145269f,
+            -161.487600f, 18.633545f,
+             -153.585137f, 35.882502f,
+             -141.131686f, 50.196376f,
+             -125.141795f, 60.409056f,
+             -106.918117f, 65.688542f,
+             -87.945283f, 65.604731f,
+             -72.507313f, 65.536534f,
+             -57.678920f, 69.832390f,
+             -44.668135f, 78.142327f,
+             -34.534908f, 89.789358f,
+             -28.104767f, 103.824631f,
+             -25.901557f, 119.104731f,
+             -28.104767f, 134.384831f,
+             -34.534908f, 148.420104f,
+             -44.668135f, 160.067134f,
+             -57.678920f, 168.377071f,
+             -72.507313f, 172.672927f,
+             -87.945283f, 172.604731f,
+             -98.958994f, 172.442364f,
+             -109.489523f, 169.211866f,
+             -118.699582f, 163.170096f,
+             -125.856872f, 154.797439f,
+             -130.392311f, 144.759613f,
+             -131.945283f, 133.854731f,
+             -130.392311f, 122.949849f,
+             -125.856872f, 112.912022f,
+             -118.699582f, 104.539366f,
+             -109.489523f, 98.497596f,
+             -98.958994f, 95.267098f,
+             -87.945283f, 95.104731f,
+             -84.371773f, 95.771023f,
+             -80.898574f, 96.843781f,
+             -77.571757f, 98.308777f,
+             -74.435452f, 100.146577f,
+             -71.531259f, 102.332803f,
+             -68.897703f, 104.838457f,
+             -66.569716f, 107.630302f,
+             -64.578177f, 110.671304f,
+             -62.949505f, 113.921127f,
+             -61.705303f, 117.336662f,
+             -60.862074f, 120.872604f,
+             -60.431003f, 124.482050f
+        };
+    
+    
+        mTriangleOffsets = new int[64];
+        mTriangleOffsetsTex = new float[64];
+    
+        mTriangleOffsets[0] = 0;
+        mTriangleOffsetsCount = 1;
+
+        Vertex t = new Vertex();
+        t.nxyz(1, 0, 0);
+        int count = vtx.length / 2;
+
+        float runningS = 0;
+        for (int ct=0; ct < (count-1); ct++) {
+            t.x = -vtx[ct*2] / 100.f;
+            t.z = vtx[ct*2+1] / 100.f;
+            t.s = runningS;
+            t.nx =  (vtx[ct*2+3] - vtx[ct*2 +1]);
+            t.ny =  (vtx[ct*2+2] - vtx[ct*2   ]);
+            float len = (float)java.lang.Math.sqrt(t.nx * t.nx + t.ny * t.ny);
+            runningS += len / 100;
+            t.nx /= len;
+            t.ny /= len;
+            t.y = -0.5f;
+            t.t = 0;
+            //Log.e("xx", "vtx " + t.x + "  " + t.y + "  " + t.z);
+            t.addToRS(rs);
+            t.y = .5f;
+            t.t = 1;
+            t.addToRS(rs);
+
+            //LOGE(" %f", runningS);
+            if((runningS*2) > mTriangleOffsetsCount) {
+                //LOGE("**** img %i  %i", gTriangleOffsetsCount, ct*2);
+                mTriangleOffsets[mTriangleOffsetsCount] = ct*2;
+                mTriangleOffsetsTex[mTriangleOffsetsCount] = t.s;
+                mTriangleOffsetsCount ++;
+            }
+        }
+
+        count = (count * 2 - 2);
+        for (int ct=0; ct < (count-2); ct+= 2) {
+            rs.triangleMeshAddTriangle(ct, ct+1, ct+2);
+            rs.triangleMeshAddTriangle(ct+1, ct+3, ct+2);
+        }
+    }
+
+
+}
+
diff --git a/libs/rs/java/Film/src/com/android/film/FilmView.java b/libs/rs/java/Film/src/com/android/film/FilmView.java
new file mode 100644
index 0000000..452d522
--- /dev/null
+++ b/libs/rs/java/Film/src/com/android/film/FilmView.java
@@ -0,0 +1,82 @@
+/*
+ * 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.film;
+
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.concurrent.Semaphore;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+
+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 FilmView extends RSSurfaceView {
+
+    public FilmView(Context context) {
+        super(context);
+
+        //setFocusable(true);
+    }
+
+    private RenderScript mRS;
+    private FilmRS mRender;
+
+    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+        super.surfaceChanged(holder, format, w, h);
+
+        mRS = createRenderScript();
+        mRender = new FilmRS();
+        mRender.init(mRS, getResources(), w, h);
+    }
+
+    @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 = true;
+        int act = ev.getAction();
+        if (act == ev.ACTION_UP) {
+            ret = false;
+        }
+        //mRender.newTouchPosition((int)ev.getX(), (int)ev.getY());
+        return ret;
+    }
+}
+
+
diff --git a/libs/rs/java/Fountain/res/raw/fountain.c b/libs/rs/java/Fountain/res/raw/fountain.c
index 54130f9..8a55406 100644
--- a/libs/rs/java/Fountain/res/raw/fountain.c
+++ b/libs/rs/java/Fountain/res/raw/fountain.c
@@ -6,7 +6,7 @@
 #pragma stateFragmentStore(parent)
 
 
-int main(void* con, int ft, int launchID) {
+int main(int launchID) {
     int count, touch, x, y, rate, maxLife, lifeShift;
     int life;
     int ct, ct2;
@@ -18,10 +18,10 @@
     int srcIdx;
     int dstIdx;
 
-    count = loadI32(con, 0, 1);
-    touch = loadI32(con, 0, 2);
-    x = loadI32(con, 0, 3);
-    y = loadI32(con, 0, 4);
+    count = loadI32(0, 1);
+    touch = loadI32(0, 2);
+    x = loadI32(0, 3);
+    y = loadI32(0, 4);
 
     rate = 4;
     maxLife = (count / rate) - 1;
@@ -34,56 +34,56 @@
         }
     }
 
-    drawRect(con, 0, 256, 0, 512);
-    contextBindProgramFragment(con, NAMED_PgmFragParts);
+    drawRect(0, 256, 0, 512);
+    contextBindProgramFragment(NAMED_PgmFragParts);
 
     if (touch) {
-        newPart = loadI32(con, 2, 0);
+        newPart = loadI32(2, 0);
         for (ct2=0; ct2<rate; ct2++) {
-            dx = scriptRand(con, 0x10000) - 0x8000;
-            dy = scriptRand(con, 0x10000) - 0x8000;
+            dx = scriptRand(0x10000) - 0x8000;
+            dy = scriptRand(0x10000) - 0x8000;
 
             idx = newPart * 5 + 1;
-            storeI32(con, 2, idx, dx);
-            storeI32(con, 2, idx + 1, dy);
-            storeI32(con, 2, idx + 2, maxLife);
-            storeI32(con, 2, idx + 3, x << 16);
-            storeI32(con, 2, idx + 4, y << 16);
+            storeI32(2, idx, dx);
+            storeI32(2, idx + 1, dy);
+            storeI32(2, idx + 2, maxLife);
+            storeI32(2, idx + 3, x << 16);
+            storeI32(2, idx + 4, y << 16);
 
             newPart++;
             if (newPart >= count) {
                 newPart = 0;
             }
         }
-        storeI32(con, 2, 0, newPart);
+        storeI32(2, 0, newPart);
     }
 
     drawCount = 0;
     for (ct=0; ct < count; ct++) {
         srcIdx = ct * 5 + 1;
 
-        dx = loadI32(con, 2, srcIdx);
-        dy = loadI32(con, 2, srcIdx + 1);
-        life = loadI32(con, 2, srcIdx + 2);
-        posx = loadI32(con, 2, srcIdx + 3);
-        posy = loadI32(con, 2, srcIdx + 4);
+        dx = loadI32(2, srcIdx);
+        dy = loadI32(2, srcIdx + 1);
+        life = loadI32(2, srcIdx + 2);
+        posx = loadI32(2, srcIdx + 3);
+        posy = loadI32(2, srcIdx + 4);
 
         if (life) {
             if (posy < (480 << 16)) {
                 dstIdx = drawCount * 9;
                 c = 0xffafcf | ((life >> lifeShift) << 24);
 
-                storeU32(con, 1, dstIdx, c);
-                storeI32(con, 1, dstIdx + 1, posx);
-                storeI32(con, 1, dstIdx + 2, posy);
+                storeU32(1, dstIdx, c);
+                storeI32(1, dstIdx + 1, posx);
+                storeI32(1, dstIdx + 2, posy);
 
-                storeU32(con, 1, dstIdx + 3, c);
-                storeI32(con, 1, dstIdx + 4, posx + 0x10000);
-                storeI32(con, 1, dstIdx + 5, posy + dy * 4);
+                storeU32(1, dstIdx + 3, c);
+                storeI32(1, dstIdx + 4, posx + 0x10000);
+                storeI32(1, dstIdx + 5, posy + dy * 4);
 
-                storeU32(con, 1, dstIdx + 6, c);
-                storeI32(con, 1, dstIdx + 7, posx - 0x10000);
-                storeI32(con, 1, dstIdx + 8, posy + dy * 4);
+                storeU32(1, dstIdx + 6, c);
+                storeI32(1, dstIdx + 7, posx - 0x10000);
+                storeI32(1, dstIdx + 8, posy + dy * 4);
                 drawCount ++;
             } else {
                 if (dy > 0) {
@@ -96,14 +96,14 @@
             dy = dy + 0x400;
             life --;
 
-            //storeI32(con, 2, srcIdx, dx);
-            storeI32(con, 2, srcIdx + 1, dy);
-            storeI32(con, 2, srcIdx + 2, life);
-            storeI32(con, 2, srcIdx + 3, posx);
-            storeI32(con, 2, srcIdx + 4, posy);
+            //storeI32(2, srcIdx, dx);
+            storeI32(2, srcIdx + 1, dy);
+            storeI32(2, srcIdx + 2, life);
+            storeI32(2, srcIdx + 3, posx);
+            storeI32(2, srcIdx + 4, posy);
         }
     }
 
-    drawTriangleArray(con, NAMED_PartBuffer, drawCount);
+    drawTriangleArray(NAMED_PartBuffer, drawCount);
     return 1;
 }
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 2a5f65d..7c46c0e 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -23,6 +23,7 @@
 using namespace android::renderscript;
 
 Context * Context::gCon = NULL;
+pthread_key_t Context::gThreadTLSKey = 0;
 
 void Context::initEGL()
 {
@@ -120,6 +121,18 @@
 
      rsc->initEGL();
 
+     ScriptTLSStruct *tlsStruct = new ScriptTLSStruct;
+     if (!tlsStruct) {
+         LOGE("Error allocating tls storage");
+         return NULL;
+     }
+     tlsStruct->mContext = rsc;
+     tlsStruct->mScript = NULL;
+     int status = pthread_setspecific(rsc->gThreadTLSKey, tlsStruct);
+     if (status) {
+         LOGE("pthread_setspecific %i", status);
+     }
+
      rsc->mStateVertex.init(rsc, rsc->mWidth, rsc->mHeight);
      rsc->setVertex(NULL);
      rsc->mStateFragment.init(rsc, rsc->mWidth, rsc->mHeight);
@@ -162,6 +175,12 @@
     int status;
     pthread_attr_t threadAttr;
 
+    status = pthread_key_create(&gThreadTLSKey, NULL);
+    if (status) {
+        LOGE("Failed to init thread tls key.");
+        return;
+    }
+
     status = pthread_attr_init(&threadAttr);
     if (status) {
         LOGE("Failed to init thread attribute.");
@@ -195,6 +214,7 @@
 
     if (mDev) {
         mDev->removeContext(this);
+        pthread_key_delete(gThreadTLSKey);
     }
 }
 
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index 10b9a13..334ef3c 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -48,6 +48,12 @@
     Context(Device *, Surface *);
     ~Context();
 
+    static pthread_key_t gThreadTLSKey;
+    struct ScriptTLSStruct {
+        Context * mContext;
+        Script * mScript;
+    };
+
 
     //StructuredAllocationContext mStateAllocation;
     ElementState mStateElement;
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index c650656..557f3ae 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -24,6 +24,11 @@
 using namespace android;
 using namespace android::renderscript;
 
+#define GET_TLS()  Context::ScriptTLSStruct * tls = \
+    (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \
+    Context * rsc = tls->mContext; \
+    ScriptC * sc = (ScriptC *) tls->mScript
+
 
 ScriptC::ScriptC()
 {
@@ -38,220 +43,212 @@
     }
 }
 
-extern "C" void matrixLoadIdentity(void *con, rsc_Matrix *mat)
+extern "C" void matrixLoadIdentity(rsc_Matrix *mat)
 {
     Matrix *m = reinterpret_cast<Matrix *>(mat);
     m->loadIdentity();
 }
 
-extern "C" void matrixLoadFloat(void *con, rsc_Matrix *mat, const float *f)
+extern "C" void matrixLoadFloat(rsc_Matrix *mat, const float *f)
 {
     Matrix *m = reinterpret_cast<Matrix *>(mat);
     m->load(f);
 }
 
-extern "C" void matrixLoadMat(void *con, rsc_Matrix *mat, const rsc_Matrix *newmat)
+extern "C" void matrixLoadMat(rsc_Matrix *mat, const rsc_Matrix *newmat)
 {
     Matrix *m = reinterpret_cast<Matrix *>(mat);
     m->load(reinterpret_cast<const Matrix *>(newmat));
 }
 
-extern "C" void matrixLoadRotate(void *con, rsc_Matrix *mat, float rot, float x, float y, float z)
+extern "C" void matrixLoadRotate(rsc_Matrix *mat, float rot, float x, float y, float z)
 {
     Matrix *m = reinterpret_cast<Matrix *>(mat);
     m->loadRotate(rot, x, y, z);
 }
 
-extern "C" void matrixLoadScale(void *con, rsc_Matrix *mat, float x, float y, float z)
+extern "C" void matrixLoadScale(rsc_Matrix *mat, float x, float y, float z)
 {
     Matrix *m = reinterpret_cast<Matrix *>(mat);
     m->loadScale(x, y, z);
 }
 
-extern "C" void matrixLoadTranslate(void *con, rsc_Matrix *mat, float x, float y, float z)
+extern "C" void matrixLoadTranslate(rsc_Matrix *mat, float x, float y, float z)
 {
     Matrix *m = reinterpret_cast<Matrix *>(mat);
     m->loadTranslate(x, y, z);
 }
 
-extern "C" void matrixLoadMultiply(void *con, rsc_Matrix *mat, const rsc_Matrix *lhs, const rsc_Matrix *rhs)
+extern "C" void matrixLoadMultiply(rsc_Matrix *mat, const rsc_Matrix *lhs, const rsc_Matrix *rhs)
 {
     Matrix *m = reinterpret_cast<Matrix *>(mat);
     m->loadMultiply(reinterpret_cast<const Matrix *>(lhs),
                     reinterpret_cast<const Matrix *>(rhs));
 }
 
-extern "C" void matrixMultiply(void *con, rsc_Matrix *mat, const rsc_Matrix *rhs)
+extern "C" void matrixMultiply(rsc_Matrix *mat, const rsc_Matrix *rhs)
 {
     Matrix *m = reinterpret_cast<Matrix *>(mat);
     m->multiply(reinterpret_cast<const Matrix *>(rhs));
 }
 
-extern "C" void matrixRotate(void *con, rsc_Matrix *mat, float rot, float x, float y, float z)
+extern "C" void matrixRotate(rsc_Matrix *mat, float rot, float x, float y, float z)
 {
     Matrix *m = reinterpret_cast<Matrix *>(mat);
     m->rotate(rot, x, y, z);
 }
 
-extern "C" void matrixScale(void *con, rsc_Matrix *mat, float x, float y, float z)
+extern "C" void matrixScale(rsc_Matrix *mat, float x, float y, float z)
 {
     Matrix *m = reinterpret_cast<Matrix *>(mat);
     m->scale(x, y, z);
 }
 
-extern "C" void matrixTranslate(void *con, rsc_Matrix *mat, float x, float y, float z)
+extern "C" void matrixTranslate(rsc_Matrix *mat, float x, float y, float z)
 {
     Matrix *m = reinterpret_cast<Matrix *>(mat);
     m->translate(x, y, z);
 }
 
 
-extern "C" const void * loadVp(void *vp, uint32_t bank, uint32_t offset)
+extern "C" const void * loadVp(uint32_t bank, uint32_t offset)
 {
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
-    return &static_cast<const uint8_t *>(env->mScript->mSlots[bank]->getPtr())[offset];
+    GET_TLS();
+    return &static_cast<const uint8_t *>(sc->mSlots[bank]->getPtr())[offset];
 }
 
-extern "C" float loadF(void *vp, uint32_t bank, uint32_t offset)
+extern "C" float loadF(uint32_t bank, uint32_t offset)
 {
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
-    //LOGE("bank %i, offset %i", bank, offset);
-    //LOGE("%p", env->mScript->mSlots[bank]->getPtr());
-    return static_cast<const float *>(env->mScript->mSlots[bank]->getPtr())[offset];
+    GET_TLS();
+    return static_cast<const float *>(sc->mSlots[bank]->getPtr())[offset];
 }
 
-extern "C" int32_t loadI32(void *vp, uint32_t bank, uint32_t offset)
+extern "C" int32_t loadI32(uint32_t bank, uint32_t offset)
 {
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
-    return static_cast<const int32_t *>(env->mScript->mSlots[bank]->getPtr())[offset];
+    GET_TLS();
+    return static_cast<const int32_t *>(sc->mSlots[bank]->getPtr())[offset];
 }
 
-extern "C" uint32_t loadU32(void *vp, uint32_t bank, uint32_t offset)
+extern "C" uint32_t loadU32(uint32_t bank, uint32_t offset)
 {
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
-    return static_cast<const uint32_t *>(env->mScript->mSlots[bank]->getPtr())[offset];
+    GET_TLS();
+    return static_cast<const uint32_t *>(sc->mSlots[bank]->getPtr())[offset];
 }
 
-extern "C" void loadEnvVec4(void *vp, uint32_t bank, uint32_t offset, rsc_Vector4 *v)
+extern "C" void loadEnvVec4(uint32_t bank, uint32_t offset, rsc_Vector4 *v)
 {
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
-    memcpy(v, &static_cast<const float *>(env->mScript->mSlots[bank]->getPtr())[offset], sizeof(rsc_Vector4));
+    GET_TLS();
+    memcpy(v, &static_cast<const float *>(sc->mSlots[bank]->getPtr())[offset], sizeof(rsc_Vector4));
 }
 
-extern "C" void loadEnvMatrix(void *vp, uint32_t bank, uint32_t offset, rsc_Matrix *m)
+extern "C" void loadEnvMatrix(uint32_t bank, uint32_t offset, rsc_Matrix *m)
 {
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
-    memcpy(m, &static_cast<const float *>(env->mScript->mSlots[bank]->getPtr())[offset], sizeof(rsc_Matrix));
+    GET_TLS();
+    memcpy(m, &static_cast<const float *>(sc->mSlots[bank]->getPtr())[offset], sizeof(rsc_Matrix));
 }
 
 
-extern "C" void storeF(void *vp, uint32_t bank, uint32_t offset, float v)
+extern "C" void storeF(uint32_t bank, uint32_t offset, float v)
 {
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
-    static_cast<float *>(env->mScript->mSlots[bank]->getPtr())[offset] = v;
+    GET_TLS();
+    static_cast<float *>(sc->mSlots[bank]->getPtr())[offset] = v;
 }
 
-extern "C" void storeI32(void *vp, uint32_t bank, uint32_t offset, int32_t v)
+extern "C" void storeI32(uint32_t bank, uint32_t offset, int32_t v)
 {
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
-    static_cast<int32_t *>(env->mScript->mSlots[bank]->getPtr())[offset] = v;
+    GET_TLS();
+    static_cast<int32_t *>(sc->mSlots[bank]->getPtr())[offset] = v;
 }
 
-extern "C" void storeU32(void *vp, uint32_t bank, uint32_t offset, uint32_t v)
+extern "C" void storeU32(uint32_t bank, uint32_t offset, uint32_t v)
 {
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
-    static_cast<uint32_t *>(env->mScript->mSlots[bank]->getPtr())[offset] = v;
+    GET_TLS();
+    static_cast<uint32_t *>(sc->mSlots[bank]->getPtr())[offset] = v;
 }
 
-extern "C" void storeEnvVec4(void *vp, uint32_t bank, uint32_t offset, const rsc_Vector4 *v)
+extern "C" void storeEnvVec4(uint32_t bank, uint32_t offset, const rsc_Vector4 *v)
 {
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
-    memcpy(&static_cast<float *>(env->mScript->mSlots[bank]->getPtr())[offset], v, sizeof(rsc_Vector4));
+    GET_TLS();
+    memcpy(&static_cast<float *>(sc->mSlots[bank]->getPtr())[offset], v, sizeof(rsc_Vector4));
 }
 
-extern "C" void storeEnvMatrix(void *vp, uint32_t bank, uint32_t offset, const rsc_Matrix *m)
+extern "C" void storeEnvMatrix(uint32_t bank, uint32_t offset, const rsc_Matrix *m)
 {
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
-    memcpy(&static_cast<float *>(env->mScript->mSlots[bank]->getPtr())[offset], m, sizeof(rsc_Matrix));
+    GET_TLS();
+    memcpy(&static_cast<float *>(sc->mSlots[bank]->getPtr())[offset], m, sizeof(rsc_Matrix));
 }
 
 
-extern "C" void color(void *vp, float r, float g, float b, float a)
+extern "C" void color(float r, float g, float b, float a)
 {
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
     glColor4f(r, g, b, a);
 }
 
-extern "C" void renderTriangleMesh(void *vp, RsTriangleMesh mesh)
+extern "C" void renderTriangleMesh(RsTriangleMesh mesh)
 {
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
-    rsi_TriangleMeshRender(env->mContext, mesh);
+    GET_TLS();
+    rsi_TriangleMeshRender(rsc, mesh);
 }
 
-extern "C" void renderTriangleMeshRange(void *vp, RsTriangleMesh mesh, uint32_t start, uint32_t count)
+extern "C" void renderTriangleMeshRange(RsTriangleMesh mesh, uint32_t start, uint32_t count)
 {
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
-    rsi_TriangleMeshRenderRange(env->mContext, mesh, start, count);
+    GET_TLS();
+    rsi_TriangleMeshRenderRange(rsc, mesh, start, count);
 }
 
-extern "C" void materialDiffuse(void *vp, float r, float g, float b, float a)
+extern "C" void materialDiffuse(float r, float g, float b, float a)
 {
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
     float v[] = {r, g, b, a};
     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, v);
 }
 
-extern "C" void materialSpecular(void *vp, float r, float g, float b, float a)
+extern "C" void materialSpecular(float r, float g, float b, float a)
 {
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
     float v[] = {r, g, b, a};
     glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, v);
 }
 
-extern "C" void lightPosition(void *vp, float x, float y, float z, float w)
+extern "C" void lightPosition(float x, float y, float z, float w)
 {
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
     float v[] = {x, y, z, w};
     glLightfv(GL_LIGHT0, GL_POSITION, v);
 }
 
-extern "C" void materialShininess(void *vp, float s)
+extern "C" void materialShininess(float s)
 {
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
     glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &s);
 }
 
-extern "C" void uploadToTexture(void *vp, RsAllocation va, uint32_t baseMipLevel)
+extern "C" void uploadToTexture(RsAllocation va, uint32_t baseMipLevel)
 {
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
-    rsi_AllocationUploadToTexture(env->mContext, va, baseMipLevel);
+    GET_TLS();
+    rsi_AllocationUploadToTexture(rsc, va, baseMipLevel);
 }
 
-extern "C" void enable(void *vp, uint32_t p)
+extern "C" void enable(uint32_t p)
 {
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
     glEnable(p);
 }
 
-extern "C" void disable(void *vp, uint32_t p)
+extern "C" void disable(uint32_t p)
 {
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
     glDisable(p);
 }
 
-extern "C" uint32_t scriptRand(void *vp, uint32_t max)
+extern "C" uint32_t scriptRand(uint32_t max)
 {
     return (uint32_t)(((float)rand()) * max / RAND_MAX);
 }
 
 // Assumes (GL_FIXED) x,y,z (GL_UNSIGNED_BYTE)r,g,b,a
-extern "C" void drawTriangleArray(void *vp, RsAllocation alloc, uint32_t count)
+extern "C" void drawTriangleArray(RsAllocation alloc, uint32_t count)
 {
+    GET_TLS();
+
     const Allocation *a = (const Allocation *)alloc;
     const uint32_t *ptr = (const uint32_t *)a->getPtr();
 
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
-    env->mContext->setupCheck();
+    rsc->setupCheck();
 
     glBindBuffer(GL_ARRAY_BUFFER, 0);
     //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tm->mBufferObjects[1]);
@@ -268,8 +265,9 @@
     glDrawArrays(GL_TRIANGLES, 0, count * 3);
 }
 
-extern "C" void drawRect(void *vp, int32_t x1, int32_t x2, int32_t y1, int32_t y2)
+extern "C" void drawRect(int32_t x1, int32_t x2, int32_t y1, int32_t y2)
 {
+    GET_TLS();
     x1 = (x1 << 16);
     x2 = (x2 << 16);
     y1 = (y1 << 16);
@@ -279,8 +277,7 @@
     static const int32_t tex[] = {0,0, 0,0x10000, 0x10000,0, 0x10000,0x10000};
 
 
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
-    env->mContext->setupCheck();
+    rsc->setupCheck();
 
     glBindBuffer(GL_ARRAY_BUFFER, 0);
     //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tm->mBufferObjects[1]);
@@ -297,40 +294,37 @@
     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
 }
 
-extern "C" void pfBindTexture(void *vp, RsProgramFragment vpf, uint32_t slot, RsAllocation va)
+extern "C" void pfBindTexture(RsProgramFragment vpf, uint32_t slot, RsAllocation va)
 {
-    //LOGE("pfBindTexture %p", vpf);
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
-    rsi_ProgramFragmentBindTexture(env->mContext,
+    GET_TLS();
+    rsi_ProgramFragmentBindTexture(rsc,
                                    static_cast<ProgramFragment *>(vpf),
                                    slot,
                                    static_cast<Allocation *>(va));
 
 }
 
-extern "C" void pfBindSampler(void *vp, RsProgramFragment vpf, uint32_t slot, RsSampler vs)
+extern "C" void pfBindSampler(RsProgramFragment vpf, uint32_t slot, RsSampler vs)
 {
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
-    rsi_ProgramFragmentBindSampler(env->mContext,
+    GET_TLS();
+    rsi_ProgramFragmentBindSampler(rsc,
                                    static_cast<ProgramFragment *>(vpf),
                                    slot,
                                    static_cast<Sampler *>(vs));
 
 }
 
-extern "C" void contextBindProgramFragmentStore(void *vp, RsProgramFragmentStore pfs)
+extern "C" void contextBindProgramFragmentStore(RsProgramFragmentStore pfs)
 {
-    //LOGE("contextBindProgramFragmentStore %p", pfs);
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
-    rsi_ContextBindProgramFragmentStore(env->mContext, pfs);
+    GET_TLS();
+    rsi_ContextBindProgramFragmentStore(rsc, pfs);
 
 }
 
-extern "C" void contextBindProgramFragment(void *vp, RsProgramFragment pf)
+extern "C" void contextBindProgramFragment(RsProgramFragment pf)
 {
-    //LOGE("contextBindProgramFragment %p", pf);
-    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
-    rsi_ContextBindProgramFragment(env->mContext, pf);
+    GET_TLS();
+    rsi_ContextBindProgramFragment(rsc, pf);
 
 }
 
@@ -388,9 +382,10 @@
 };
 
 
-bool ScriptC::run(Context *rsc, uint32_t launchID)
+bool ScriptC::run(Context *rsc, uint32_t launchIndex)
 {
-    Env e = {rsc, this};
+    Context::ScriptTLSStruct * tls = 
+    (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey);
 
     if (mEnviroment.mFragmentStore.get()) {
         rsc->setFragmentStore(mEnviroment.mFragmentStore.get());
@@ -402,7 +397,9 @@
         rsc->setVertex(mEnviroment.mVertex.get());
     }
 
-    return mProgram.mScript(&e, &scriptCPtrTable, launchID) != 0;
+    tls->mScript = this;
+    return mProgram.mScript(launchIndex, &scriptCPtrTable) != 0;
+    tls->mScript = NULL;
 }
 
 ScriptCState::ScriptCState()
diff --git a/libs/rs/rsScriptC.h b/libs/rs/rsScriptC.h
index 55a2cc6..c46901b1 100644
--- a/libs/rs/rsScriptC.h
+++ b/libs/rs/rsScriptC.h
@@ -52,12 +52,6 @@
     ACCscript*    mAccScript;
 
     virtual bool run(Context *, uint32_t launchID);
-
-    struct Env {
-        Context *mContext;
-        ScriptC *mScript;
-    };
-
 };
 
 class ScriptCState