Update fountain and add writable flag to script slots.
diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java
index aab8c21..3061b1e 100644
--- a/graphics/java/android/renderscript/Element.java
+++ b/graphics/java/android/renderscript/Element.java
@@ -223,6 +223,52 @@
             return this;
         }
 
+        public Builder addFloat(Element.DataKind dk) {
+            add(DataType.FLOAT, dk, false, 32, null);
+            return this;
+        }
+
+        public Builder addFloat(Element.DataKind dk, String name) {
+            add(DataType.FLOAT, dk, false, 32, name);
+            return this;
+        }
+
+        public Builder addFloatXY() {
+            add(DataType.FLOAT, DataKind.X, false, 32, null);
+            add(DataType.FLOAT, DataKind.Y, false, 32, null);
+            return this;
+        }
+
+        public Builder addFloatXYZ() {
+            add(DataType.FLOAT, DataKind.X, false, 32, null);
+            add(DataType.FLOAT, DataKind.Y, false, 32, null);
+            add(DataType.FLOAT, DataKind.Z, false, 32, null);
+            return this;
+        }
+
+        public Builder addFloatRGB() {
+            add(DataType.FLOAT, DataKind.RED, false, 32, null);
+            add(DataType.FLOAT, DataKind.GREEN, false, 32, null);
+            add(DataType.FLOAT, DataKind.BLUE, false, 32, null);
+            return this;
+        }
+
+        public Builder addFloatRGBA() {
+            add(DataType.FLOAT, DataKind.RED, false, 32, null);
+            add(DataType.FLOAT, DataKind.GREEN, false, 32, null);
+            add(DataType.FLOAT, DataKind.BLUE, false, 32, null);
+            add(DataType.FLOAT, DataKind.ALPHA, false, 32, null);
+            return this;
+        }
+
+        public Builder addUNorm8RGBA() {
+            add(DataType.UNSIGNED, DataKind.RED, true, 8, null);
+            add(DataType.UNSIGNED, DataKind.GREEN, true, 8, null);
+            add(DataType.UNSIGNED, DataKind.BLUE, true, 8, null);
+            add(DataType.UNSIGNED, DataKind.ALPHA, true, 8, null);
+            return this;
+        }
+
         static synchronized Element internalCreate(RenderScript rs, Builder b) {
             rs.nElementBegin();
             for (int ct=0; ct < b.mEntryCount; ct++) {
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index b98a48ab..ab263ed 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -142,7 +142,7 @@
     native void nScriptSetClearDepth(int script, float depth);
     native void nScriptSetClearStencil(int script, int stencil);
     native void nScriptSetTimeZone(int script, byte[] timeZone);
-    native void nScriptSetType(int type, String name, int slot);
+    native void nScriptSetType(int type, boolean writable, String name, int slot);
     native void nScriptSetRoot(boolean isRoot);
 
     native void nScriptCBegin();
diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java
index 47479d8..5b9eb553 100644
--- a/graphics/java/android/renderscript/Script.java
+++ b/graphics/java/android/renderscript/Script.java
@@ -24,6 +24,7 @@
 
     boolean mIsRoot;
     Type[] mTypes;
+    boolean[] mWritable;
 
     Script(int id, RenderScript rs) {
         super(rs);
@@ -67,11 +68,13 @@
         boolean mIsRoot = false;
         Type[] mTypes;
         String[] mNames;
+        boolean[] mWritable;
 
         Builder(RenderScript rs) {
             mRS = rs;
             mTypes = new Type[MAX_SLOT];
             mNames = new String[MAX_SLOT];
+            mWritable = new boolean[MAX_SLOT];
         }
 
         public void setType(Type t, int slot) {
@@ -84,11 +87,15 @@
             mNames[slot] = name;
         }
 
+        public void setType(boolean writable, int slot) {
+            mWritable[slot] = writable;
+        }
+
         void transferCreate() {
             mRS.nScriptSetRoot(mIsRoot);
             for(int ct=0; ct < mTypes.length; ct++) {
                 if(mTypes[ct] != null) {
-                    mRS.nScriptSetType(mTypes[ct].mID, mNames[ct], ct);
+                    mRS.nScriptSetType(mTypes[ct].mID, mWritable[ct], mNames[ct], ct);
                 }
             }
         }
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 5780e02..4d6f252 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -825,15 +825,15 @@
 }
 
 static void
-nScriptSetType(JNIEnv *_env, jobject _this, jint type, jstring _str, jint slot)
+nScriptSetType(JNIEnv *_env, jobject _this, jint type, jboolean writable, jstring _str, jint slot)
 {
     RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    LOG_API("nScriptCAddType, con(%p), type(%p), slot(%i)", con, (RsType)type, slot);
+    LOG_API("nScriptCAddType, con(%p), type(%p), writable(%i), slot(%i)", con, (RsType)type, writable, slot);
     const char* n = NULL;
     if (_str) {
         n = _env->GetStringUTFChars(_str, NULL);
     }
-    rsScriptSetType((RsType)type, slot, n);
+    rsScriptSetType((RsType)type, slot, writable, n);
     if (n) {
         _env->ReleaseStringUTFChars(_str, n);
     }
@@ -1381,7 +1381,7 @@
 {"nScriptSetClearDepth",           "(IF)V",                                (void*)nScriptSetClearDepth },
 {"nScriptSetClearStencil",         "(II)V",                                (void*)nScriptSetClearStencil },
 {"nScriptSetTimeZone",             "(I[B)V",                               (void*)nScriptSetTimeZone },
-{"nScriptSetType",                 "(ILjava/lang/String;I)V",              (void*)nScriptSetType },
+{"nScriptSetType",                 "(IZLjava/lang/String;I)V",             (void*)nScriptSetType },
 {"nScriptSetRoot",                 "(Z)V",                                 (void*)nScriptSetRoot },
 
 {"nScriptCBegin",                  "()V",                                  (void*)nScriptCBegin },
diff --git a/libs/rs/java/Fountain/res/raw/fountain.c b/libs/rs/java/Fountain/res/raw/fountain.c
index 6e6afcd..e7804a5 100644
--- a/libs/rs/java/Fountain/res/raw/fountain.c
+++ b/libs/rs/java/Fountain/res/raw/fountain.c
@@ -1,86 +1,52 @@
 // Fountain test script
-
 #pragma version(1)
 #pragma stateVertex(default)
-#pragma stateFragment(PgmFragParts)
-#pragma stateFragmentStore(PFSBlend)
-
+#pragma stateFragment(default)
+#pragma stateFragmentStore(default)
 
 int main(int launchID) {
     int ct;
-    int count = loadI32(0, OFFSETOF_SomeData_count);
-    int touch = loadI32(0, OFFSETOF_SomeData_touch);
-    int rate = 4;
-    int maxLife = (count / rate) - 1;
+    int count = Control_count - 1;
+    int rate = Control_rate;
+    float *dataF = loadArrayF(1, 0);
+    float height = getHeight();
 
-    if (touch) {
-        int x = loadI32(0, OFFSETOF_SomeData_x);
-        int y = loadI32(0, OFFSETOF_SomeData_y);
-        int newPart = loadI32(2, 0);
-        for (ct=0; ct<rate; ct++) {
-            int idx = newPart * 5 + 1;
-            storeF(2, idx, randf(1.f) - 0.5f);
-            storeF(2, idx + 1, randf(1.f) - 0.5f);
-            storeI32(2, idx + 2, maxLife);
-            storeF(2, idx + 3, x);
-            storeF(2, idx + 4, y);
+    if (rate) {
+        debugI32("rate", rate);
+        int *dataI = loadArrayI32(1, 0);
+        float rMax = ((float)rate) * 0.005f;
+        int x = Control_x;
+        int y = Control_y;
+        int newPart = loadI32(1, count * 5);
+        int c = colorFloatRGBAtoUNorm8(Control_r, Control_g, Control_b, 0.99f);
+
+        while (rate--) {
+            int idx = newPart * 5;
+            vec2Rand(dataF + idx, rMax);
+            dataF[idx + 2] = x;
+            dataF[idx + 3] = y;
+            dataI[idx + 4] = c;
             newPart++;
             if (newPart >= count) {
                 newPart = 0;
             }
         }
-        storeI32(2, 0, newPart);
+        storeI32(1, count * 5, newPart);
     }
 
-    int drawCount = 0;
-    float height = getHeight();
     for (ct=0; ct < count; ct++) {
-        int srcIdx = ct * 5 + 1;
-
-        int life = loadI32(2, srcIdx + 2);
-
-        if (life) {
-            float posx = loadF(2, srcIdx + 3);
-            float posy = loadF(2, srcIdx + 4);
-            float dx = loadF(2, srcIdx);
-            float dy = loadF(2, srcIdx + 1);
-            if (posy < height) {
-                int dstIdx = drawCount * 9;
-                int c = 0xcfcfcfcf;
-
-                storeI32(1, dstIdx, c);
-                storeF(1, dstIdx + 1, posx);
-                storeF(1, dstIdx + 2, posy);
-
-                storeI32(1, dstIdx + 3, c);
-                storeF(1, dstIdx + 4, posx + 1.f);
-                storeF(1, dstIdx + 5, posy + dy);
-
-                storeI32(1, dstIdx + 6, c);
-                storeF(1, dstIdx + 7, posx - 1.f);
-                storeF(1, dstIdx + 8, posy + dy);
-                drawCount ++;
-            } else {
-                if (dy > 0) {
-                    dy *= -0.5f;
-                }
-            }
-
-            posx = posx + dx;
-            posy = posy + dy;
-            dy = dy + 0.05f;
-            life --;
-
-            //storeI32(2, srcIdx, dx);
-            storeF(2, srcIdx + 1, dy);
-            storeI32(2, srcIdx + 2, life);
-            storeF(2, srcIdx + 3, posx);
-            storeF(2, srcIdx + 4, posy);
+        float dy = dataF[1] + 0.15f;
+        float posy = dataF[3] + dy;
+        if ((posy > height) && (dy > 0)) {
+            dy *= -0.3f;
         }
+        dataF[1] = dy;
+        dataF[2] += dataF[0];
+        dataF[3] = posy;
+        dataF += 5;
     }
 
-    //drawTriangleArray(NAMED_PartBuffer, drawCount);
     uploadToBufferObject(NAMED_PartBuffer);
-    drawSimpleMeshRange(NAMED_PartMesh, 0, drawCount * 3);
+    drawSimpleMeshRange(NAMED_PartMesh, 0, count);
     return 1;
 }
diff --git a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
index da4eeb4..da9eda8 100644
--- a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
+++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
@@ -16,26 +16,22 @@
 
 package com.android.fountain;
 
-import java.io.Writer;
-
-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.renderscript.*;
 import android.util.Log;
 
 
 public class FountainRS {
-    public static final int PART_COUNT = 4000;
+    public static final int PART_COUNT = 20000;
 
     static class SomeData {
         public int x;
         public int y;
-        public int touch;
         public int rate;
         public int count;
+        public float r;
+        public float g;
+        public float b;
     }
 
     public FountainRS() {
@@ -47,8 +43,18 @@
         initRS();
     }
 
-    public void newTouchPosition(int x, int y) {
-        mSD.touch = 1;
+    public void newTouchPosition(int x, int y, int rate) {
+        if (mSD.rate == 0) {
+            mSD.r = ((x & 0x1) != 0) ? 0.f : 1.f;
+            mSD.g = ((x & 0x2) != 0) ? 0.f : 1.f;
+            mSD.b = ((x & 0x4) != 0) ? 0.f : 1.f;
+            if ((mSD.r + mSD.g + mSD.b) < 0.9f) {
+                mSD.r = 0.8f;
+                mSD.g = 0.5f;
+                mSD.b = 1.f;
+            }
+        }
+        mSD.rate = rate;
         mSD.x = x;
         mSD.y = y;
         mIntAlloc.data(mSD);
@@ -62,50 +68,29 @@
     private RenderScript mRS;
     private Allocation mIntAlloc;
     private Allocation mPartAlloc;
-    private Allocation mVertAlloc;
     private Script mScript;
-    private ProgramStore mPFS;
-    private ProgramFragment mPF;
     private SimpleMesh mSM;
-
-    private Bitmap mBackground;
-
-    SomeData mSD = new SomeData();
+    private SomeData mSD;
     private Type mSDType;
 
     private void initRS() {
         mSD = new SomeData();
         mSDType = Type.createFromClass(mRS, SomeData.class, 1, "SomeData");
         mIntAlloc = Allocation.createTyped(mRS, mSDType);
-        mVertAlloc = Allocation.createSized(mRS, Element.USER_I32, PART_COUNT * 5 + 1);
-
-        ProgramStore.Builder bs = new ProgramStore.Builder(mRS, null, null);
-        bs.setBlendFunc(ProgramStore.BlendSrcFunc.SRC_ALPHA, ProgramStore.BlendDstFunc.ONE);
-        bs.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
-        bs.setDepthMask(false);
-        bs.setDitherEnable(false);
-        mPFS = bs.create();
-        mPFS.setName("PFSBlend");
-
-        ProgramFragment.Builder bf = new ProgramFragment.Builder(mRS, null, null);
-        mPF = bf.create();
-        mPF.setName("PgmFragParts");
-
         mSD.count = PART_COUNT;
         mIntAlloc.data(mSD);
 
         Element.Builder eb = new Element.Builder(mRS);
-        eb.add(Element.DataType.UNSIGNED, Element.DataKind.RED, true, 8);
-        eb.add(Element.DataType.UNSIGNED, Element.DataKind.GREEN, true, 8);
-        eb.add(Element.DataType.UNSIGNED, Element.DataKind.BLUE, true, 8);
-        eb.add(Element.DataType.UNSIGNED, Element.DataKind.ALPHA, true, 8);
-        eb.add(Element.DataType.FLOAT, Element.DataKind.X, false, 32);
-        eb.add(Element.DataType.FLOAT, Element.DataKind.Y, false, 32);
+        eb.addFloat(Element.DataKind.USER); //dx
+        eb.addFloat(Element.DataKind.USER); //dy
+        eb.addFloatXY();
+        eb.addUNorm8RGBA();
         Element primElement = eb.create();
 
+
         SimpleMesh.Builder smb = new SimpleMesh.Builder(mRS);
-        int vtxSlot = smb.addVertexType(primElement, PART_COUNT * 3);
-        smb.setPrimitive(Primitive.TRIANGLE);
+        int vtxSlot = smb.addVertexType(primElement, PART_COUNT);
+        smb.setPrimitive(Primitive.POINT);
         mSM = smb.create();
         mSM.setName("PartMesh");
 
@@ -118,13 +103,12 @@
         ScriptC.Builder sb = new ScriptC.Builder(mRS);
         sb.setScript(mRes, R.raw.fountain);
         sb.setRoot(true);
-        sb.setType(mSDType, 0);
+        sb.setType(mSDType, "Control", 0);
         mScript = sb.create();
         mScript.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
 
         mScript.bindAllocation(mIntAlloc, 0);
         mScript.bindAllocation(mPartAlloc, 1);
-        mScript.bindAllocation(mVertAlloc, 2);
         mRS.contextBindRootScript(mScript);
     }
 
diff --git a/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java b/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java
index be8b24e..2768e2c 100644
--- a/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java
+++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java
@@ -61,13 +61,18 @@
     @Override
     public boolean onTouchEvent(MotionEvent ev)
     {
-        boolean ret = true;
         int act = ev.getAction();
         if (act == ev.ACTION_UP) {
-            ret = false;
+            mRender.newTouchPosition(0, 0, 0);
+            return false;
         }
-        mRender.newTouchPosition((int)ev.getX(), (int)ev.getY());
-        return ret;
+        float rate = (ev.getPressure() * 50.f);
+        rate *= rate;
+        if(rate > 2000.f) {
+            rate = 2000.f;
+        }
+        mRender.newTouchPosition((int)ev.getX(), (int)ev.getY(), (int)rate);
+        return true;
     }
 }
 
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 105142b..0df237f 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -315,6 +315,7 @@
 ScriptSetType {
 	param RsType type
 	param uint32_t slot
+	param bool isWritable
 	param const char * name
 	}
 
diff --git a/libs/rs/rsScript.cpp b/libs/rs/rsScript.cpp
index 75c994b..6bcb8f2 100644
--- a/libs/rs/rsScript.cpp
+++ b/libs/rs/rsScript.cpp
@@ -76,11 +76,12 @@
     s->mEnviroment.mClearStencil = v;
 }
 
-void rsi_ScriptSetType(Context * rsc, RsType vt, uint32_t slot, const char *name)
+void rsi_ScriptSetType(Context * rsc, RsType vt, uint32_t slot, bool writable, const char *name)
 {
     ScriptCState *ss = &rsc->mScriptC;
     const Type *t = static_cast<const Type *>(vt);
     ss->mConstantBufferTypes[slot].set(t);
+    ss->mSlotWritable[slot] = writable;
     if (name) {
         ss->mSlotNames[slot].setTo(name);
     } else {
diff --git a/libs/rs/rsScript.h b/libs/rs/rsScript.h
index dc66763..60f83a6 100644
--- a/libs/rs/rsScript.h
+++ b/libs/rs/rsScript.h
@@ -61,6 +61,7 @@
     ObjectBaseRef<Allocation> mSlots[MAX_SCRIPT_BANKS];
     ObjectBaseRef<const Type> mTypes[MAX_SCRIPT_BANKS];
     String8 mSlotNames[MAX_SCRIPT_BANKS];
+    bool mSlotWritable[MAX_SCRIPT_BANKS];
 
     virtual bool run(Context *, uint32_t launchID) = 0;
 };
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index ced2516..db4fd09 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -93,6 +93,7 @@
     for (uint32_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
         mConstantBufferTypes[ct].clear();
         mSlotNames[ct].setTo("");
+        mSlotWritable[ct] = false;
     }
 
     memset(&mEnviroment, 0, sizeof(mEnviroment));
@@ -341,6 +342,7 @@
     for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
         s->mTypes[ct].set(ss->mConstantBufferTypes[ct].get());
         s->mSlotNames[ct] = ss->mSlotNames[ct];
+        s->mSlotWritable[ct] = ss->mSlotWritable[ct];
     }
 
     ss->clear();
diff --git a/libs/rs/rsScriptC.h b/libs/rs/rsScriptC.h
index 32a9079..302515e 100644
--- a/libs/rs/rsScriptC.h
+++ b/libs/rs/rsScriptC.h
@@ -70,6 +70,7 @@
 
     ObjectBaseRef<const Type> mConstantBufferTypes[MAX_SCRIPT_BANKS];
     String8 mSlotNames[MAX_SCRIPT_BANKS];
+    bool mSlotWritable[MAX_SCRIPT_BANKS];
 
     void clear();
     void runCompiler(Context *rsc);
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index c13894b..0ecdf9a 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -465,6 +465,14 @@
 }
 
 
+static void SC_vec2Rand(float *vec, float maxLen)
+{
+    float angle = SC_randf(PI * 2);
+    float len = SC_randf(maxLen);
+    vec[0] = len * sinf(angle);
+    vec[1] = len * cosf(angle);
+}
+
 
 
 //////////////////////////////////////////////////////////////////////////////
@@ -780,6 +788,24 @@
     return rsc->getHeight();
 }
 
+static uint32_t SC_colorFloatRGBAtoUNorm8(float r, float g, float b, float a)
+{
+    uint32_t c = 0;
+    c |= (uint32_t)(r * 255.f + 0.5f);
+    c |= ((uint32_t)(g * 255.f + 0.5f)) << 8;
+    c |= ((uint32_t)(b * 255.f + 0.5f)) << 16;
+    c |= ((uint32_t)(a * 255.f + 0.5f)) << 24;
+    return c;
+}
+
+static uint32_t SC_colorFloatRGBAto565(float r, float g, float b)
+{
+    uint32_t ir = (uint32_t)(r * 255.f + 0.5f);
+    uint32_t ig = (uint32_t)(g * 255.f + 0.5f);
+    uint32_t ib = (uint32_t)(b * 255.f + 0.5f);
+    return rs888to565(ir, ig, ib);
+}
+
 //////////////////////////////////////////////////////////////////////////////
 // Class implementation
 //////////////////////////////////////////////////////////////////////////////
@@ -937,6 +963,10 @@
     { "matrixTranslate", (void *)&SC_matrixTranslate,
         "void", "(float *mat, float x, float y, float z)" },
 
+    // vector
+    { "vec2Rand", (void *)&SC_vec2Rand,
+        "void", "(float *vec, float maxLen)" },
+
     // context
     { "bindProgramFragment", (void *)&SC_bindProgramFragment,
         "void", "(int)" },
@@ -999,6 +1029,12 @@
     { "uploadToBufferObject", (void *)&SC_uploadToBufferObject,
         "void", "(int)" },
 
+    { "colorFloatRGBAtoUNorm8", (void *)&SC_colorFloatRGBAtoUNorm8,
+        "int", "(float, float, float, float)" },
+    { "colorFloatRGBto565", (void *)&SC_colorFloatRGBAto565,
+        "int", "(float, float, float)" },
+
+
     { "getWidth", (void *)&SC_getWidth,
         "int", "()" },
     { "getHeight", (void *)&SC_getHeight,