Begin implementing SimpleMesh and fix some bugs with refcounting and java object destruction tracking.
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 3b6571a..ede475f 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -43,8 +43,11 @@
     }
 
     public void destroy() {
+        if(mDestroyed) {
+            throw new IllegalStateException("Object already destroyed.");
+        }
+        mDestroyed = true;
         mRS.nAllocationDestroy(mID);
-        mID = 0;
     }
 
     public void data(int[] d) {
@@ -160,17 +163,27 @@
         mBitmapOptions.inScaled = false;
     }
 
-    static public Allocation createTyped(RenderScript rs, Type type) {
+    static public Allocation createTyped(RenderScript rs, Type type)
+        throws IllegalArgumentException {
+
+        if(type.mID == 0) {
+            throw new IllegalStateException("Bad Type");
+        }
         int id = rs.nAllocationCreateTyped(type.mID);
         return new Allocation(id, rs);
     }
 
-    static public Allocation createSized(RenderScript rs, Element e, int count) {
+    static public Allocation createSized(RenderScript rs, Element e, int count)
+        throws IllegalArgumentException {
+
         int id;
         if(e.mIsPredefined) {
             id = rs.nAllocationCreatePredefSized(e.mPredefinedID, count);
         } else {
             id = rs.nAllocationCreateSized(e.mID, count);
+            if(id == 0) {
+                throw new IllegalStateException("Bad element.");
+            }
         }
         return new Allocation(id, rs);
     }
diff --git a/graphics/java/android/renderscript/BaseObj.java b/graphics/java/android/renderscript/BaseObj.java
index f70aee5..f760035 100644
--- a/graphics/java/android/renderscript/BaseObj.java
+++ b/graphics/java/android/renderscript/BaseObj.java
@@ -27,6 +27,7 @@
     BaseObj(RenderScript rs) {
         mRS = rs;
         mID = 0;
+        mDestroyed = false;
     }
 
     public int getID() {
@@ -34,6 +35,7 @@
     }
 
     int mID;
+    boolean mDestroyed;
     String mName;
     RenderScript mRS;
 
@@ -57,7 +59,7 @@
 
     protected void finalize() throws Throwable
     {
-        if (mID != 0) {
+        if (!mDestroyed) {
             Log.v(RenderScript.LOG_TAG,
                   "Element finalized without having released the RS reference.");
         }
diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java
index 409d267..14d9115 100644
--- a/graphics/java/android/renderscript/Element.java
+++ b/graphics/java/android/renderscript/Element.java
@@ -137,8 +137,11 @@
         if(mIsPredefined) {
             throw new IllegalStateException("Attempting to destroy a predefined Element.");
         }
+        if(mDestroyed) {
+            throw new IllegalStateException("Object already destroyed.");
+        }
+        mDestroyed = true;
         mRS.nElementDestroy(mID);
-        mID = 0;
     }
 
 
@@ -206,7 +209,7 @@
                     if (en.mIsNormalized) {
                         norm = 1;
                     }
-                    rs.nElementAdd(en.mType.mID, en.mKind.mID, norm, en.mBits);
+                    rs.nElementAdd(en.mKind.mID, en.mType.mID, norm, en.mBits);
                 }
             }
             int id = rs.nElementCreate();
diff --git a/graphics/java/android/renderscript/Primitive.java b/graphics/java/android/renderscript/Primitive.java
new file mode 100644
index 0000000..7925cac
--- /dev/null
+++ b/graphics/java/android/renderscript/Primitive.java
@@ -0,0 +1,37 @@
+/*
+ * 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 android.renderscript;
+
+/**
+ * @hide
+ **/
+public enum Primitive {
+    POINT (0),
+    LINE (1),
+    LINE_STRIP (2),
+    TRIANGLE (3),
+    TRIANGLE_STRIP (4),
+    TRIANGLE_FAN (5);
+
+    int mID;
+    Primitive(int id) {
+        mID = id;
+    }
+}
+
+
+
diff --git a/graphics/java/android/renderscript/ProgramFragment.java b/graphics/java/android/renderscript/ProgramFragment.java
index c228cf2..09c4d9a 100644
--- a/graphics/java/android/renderscript/ProgramFragment.java
+++ b/graphics/java/android/renderscript/ProgramFragment.java
@@ -46,8 +46,11 @@
     }
 
     public void destroy() {
+        if(mDestroyed) {
+            throw new IllegalStateException("Object already destroyed.");
+        }
+        mDestroyed = true;
         mRS.nProgramFragmentStoreDestroy(mID);
-        mID = 0;
     }
 
     public void bindTexture(Allocation va, int slot)
diff --git a/graphics/java/android/renderscript/ProgramStore.java b/graphics/java/android/renderscript/ProgramStore.java
index 9039621..f8b59bd 100644
--- a/graphics/java/android/renderscript/ProgramStore.java
+++ b/graphics/java/android/renderscript/ProgramStore.java
@@ -81,8 +81,11 @@
     }
 
     public void destroy() {
+        if(mDestroyed) {
+            throw new IllegalStateException("Object already destroyed.");
+        }
+        mDestroyed = true;
         mRS.nProgramFragmentStoreDestroy(mID);
-        mID = 0;
     }
 
 
diff --git a/graphics/java/android/renderscript/ProgramVertex.java b/graphics/java/android/renderscript/ProgramVertex.java
index c4f7759..74c005f 100644
--- a/graphics/java/android/renderscript/ProgramVertex.java
+++ b/graphics/java/android/renderscript/ProgramVertex.java
@@ -34,8 +34,11 @@
     }
 
     public void destroy() {
+        if(mDestroyed) {
+            throw new IllegalStateException("Object already destroyed.");
+        }
+        mDestroyed = true;
         mRS.nProgramVertexDestroy(mID);
-        mID = 0;
     }
 
     public void bindAllocation(MatrixAllocation va) {
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 0fb450e..8fc5ad5 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -178,6 +178,11 @@
     native void nLightSetColor(int l, float r, float g, float b);
     native void nLightSetPosition(int l, float x, float y, float z);
 
+    native void nSimpleMeshDestroy(int id);
+    native int  nSimpleMeshCreate(int batchID, int idxID, int[] vtxID, int prim);
+    native void nSimpleMeshBindVertex(int id, int alloc, int slot);
+    native void nSimpleMeshBindIndex(int id, int alloc);
+
 
     private int     mDev;
     private int     mContext;
diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java
index 9696cea..1c7b32b 100644
--- a/graphics/java/android/renderscript/Script.java
+++ b/graphics/java/android/renderscript/Script.java
@@ -28,8 +28,11 @@
     }
 
     public void destroy() {
+        if(mDestroyed) {
+            throw new IllegalStateException("Object already destroyed.");
+        }
+        mDestroyed = true;
         mRS.nScriptDestroy(mID);
-        mID = 0;
     }
 
     public void bindAllocation(Allocation va, int slot) {
diff --git a/graphics/java/android/renderscript/SimpleMesh.java b/graphics/java/android/renderscript/SimpleMesh.java
new file mode 100644
index 0000000..484849b
--- /dev/null
+++ b/graphics/java/android/renderscript/SimpleMesh.java
@@ -0,0 +1,179 @@
+/*
+ * 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 android.renderscript;
+
+import android.util.Config;
+import android.util.Log;
+
+/**
+ * @hide
+ *
+ **/
+public class SimpleMesh extends BaseObj {
+    Type[] mVertexTypes;
+    Type mIndexType;
+    //Type mBatcheType;
+    Primitive mPrimitive;
+
+    SimpleMesh(int id, RenderScript rs) {
+        super(rs);
+        mID = id;
+    }
+
+    public void destroy() {
+        if(mDestroyed) {
+            throw new IllegalStateException("Object already destroyed.");
+        }
+        mDestroyed = true;
+        mRS.nSimpleMeshDestroy(mID);
+    }
+
+    public void bindVertexAllocation(Allocation a, int slot) {
+        mRS.nSimpleMeshBindVertex(mID, a.mID, slot);
+    }
+
+    public void bindIndexAllocation(Allocation a) {
+        mRS.nSimpleMeshBindIndex(mID, a.mID);
+    }
+
+    public Allocation createVertexAllocation(int slot) {
+        return Allocation.createTyped(mRS, mVertexTypes[slot]);
+    }
+
+    public Allocation createIndexAllocation() {
+        return Allocation.createTyped(mRS, mIndexType);
+    }
+
+
+    public static class Builder {
+        RenderScript mRS;
+
+        class Entry {
+            Type t;
+            Element e;
+            int size;
+        }
+
+        int mVertexTypeCount;
+        Entry[] mVertexTypes;
+        Entry mIndexType;
+        //Entry mBatchType;
+        Primitive mPrimitive;
+
+
+        public Builder(RenderScript rs) {
+            mRS = rs;
+            mVertexTypeCount = 0;
+            mVertexTypes = new Entry[16];
+            mIndexType = new Entry();
+        }
+
+        public int addVertexType(Type t) throws IllegalStateException {
+            if(mVertexTypeCount >= mVertexTypes.length) {
+                throw new IllegalStateException("Max vertex types exceeded.");
+            }
+
+            int addedIndex = mVertexTypeCount;
+            mVertexTypes[mVertexTypeCount] = new Entry();
+            mVertexTypes[mVertexTypeCount].t = t;
+            mVertexTypeCount++;
+            return addedIndex;
+        }
+
+        public int addVertexType(Element e, int size) throws IllegalStateException {
+            if(mVertexTypeCount >= mVertexTypes.length) {
+                throw new IllegalStateException("Max vertex types exceeded.");
+            }
+
+            int addedIndex = mVertexTypeCount;
+            mVertexTypes[mVertexTypeCount] = new Entry();
+            mVertexTypes[mVertexTypeCount].e = e;
+            mVertexTypes[mVertexTypeCount].size = size;
+            mVertexTypeCount++;
+            return addedIndex;
+        }
+
+        public void setIndexType(Type t) {
+            mIndexType.t = t;
+            mIndexType.e = null;
+            mIndexType.size = 0;
+        }
+
+        public void setIndexType(Element e, int size) {
+            mIndexType.t = null;
+            mIndexType.e = e;
+            mIndexType.size = size;
+        }
+
+        public void setPrimitive(Primitive p) {
+            mPrimitive = p;
+        }
+
+
+        Type newType(Element e, int size) {
+            Type.Builder tb = new Type.Builder(mRS, e);
+            tb.add(Dimension.X, size);
+            return tb.create();
+        }
+
+        static synchronized SimpleMesh internalCreate(RenderScript rs, Builder b) {
+            Type[] toDestroy = new Type[18];
+            int toDestroyCount = 0;
+
+            int indexID = 0;
+            if(b.mIndexType.t != null) {
+                indexID = b.mIndexType.t.mID;
+            } else if(b.mIndexType.size != 0) {
+                b.mIndexType.t = b.newType(b.mIndexType.e, b.mIndexType.size);
+                indexID = b.mIndexType.t.mID;
+                toDestroy[toDestroyCount++] = b.mIndexType.t;
+            }
+
+            int[] IDs = new int[b.mVertexTypeCount];
+            for(int ct=0; ct < b.mVertexTypeCount; ct++) {
+                if(b.mVertexTypes[ct].t != null) {
+                    IDs[ct] = b.mVertexTypes[ct].t.mID;
+                } else {
+                    b.mVertexTypes[ct].t = b.newType(b.mVertexTypes[ct].e, b.mVertexTypes[ct].size);
+                    IDs[ct] = b.mVertexTypes[ct].t.mID;
+                    toDestroy[toDestroyCount++] = b.mVertexTypes[ct].t;
+                }
+            }
+
+            int id = rs.nSimpleMeshCreate(0, indexID, IDs, b.mPrimitive.mID);
+            for(int ct=0; ct < toDestroyCount; ct++) {
+                toDestroy[ct].destroy();
+            }
+
+            return new SimpleMesh(id, rs);
+        }
+
+        public SimpleMesh create() {
+            Log.e("rs", "SimpleMesh create");
+            SimpleMesh sm = internalCreate(mRS, this);
+            sm.mVertexTypes = new Type[mVertexTypeCount];
+            for(int ct=0; ct < mVertexTypeCount; ct++) {
+                sm.mVertexTypes[ct] = mVertexTypes[ct].t;
+            }
+            sm.mIndexType = mIndexType.t;
+            sm.mPrimitive = mPrimitive;
+            return sm;
+        }
+    }
+
+}
+
diff --git a/graphics/java/android/renderscript/Type.java b/graphics/java/android/renderscript/Type.java
index 4078c8a..a5fc603 100644
--- a/graphics/java/android/renderscript/Type.java
+++ b/graphics/java/android/renderscript/Type.java
@@ -16,31 +16,31 @@
 
 package android.renderscript;
 
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import android.content.res.Resources;
-import android.os.Bundle;
 import android.util.Config;
 import android.util.Log;
 
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
 
 /**
  * @hide
  *
  **/
 public class Type extends BaseObj {
+    Dimension[] mDimensions;
+    int[] mValues;
+    Element mElement;
+
+
     Type(int id, RenderScript rs) {
         super(rs);
         mID = id;
     }
 
     public void destroy() {
+        if(mDestroyed) {
+            throw new IllegalStateException("Object already destroyed.");
+        }
+        mDestroyed = true;
         mRS.nTypeDestroy(mID);
-        mID = 0;
     }
 
     public static class Builder {
@@ -85,7 +85,15 @@
         }
 
         public Type create() {
-            return internalCreate(mRS, this);
+            Type t = internalCreate(mRS, this);
+            t.mElement = mElement;
+            t.mDimensions = new Dimension[mEntryCount];
+            t.mValues = new int[mEntryCount];
+            for(int ct=0; ct < mEntryCount; ct++) {
+                t.mDimensions[ct] = mEntries[ct].mDim;
+                t.mValues[ct] = mEntries[ct].mValue;
+            }
+            return t;
         }
     }
 
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index e2a8a27..06525fc 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -1079,6 +1079,45 @@
 
 // ---------------------------------------------------------------------------
 
+static void
+nSimpleMeshDestroy(JNIEnv *_env, jobject _this, jint s)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nSimpleMeshDestroy, con(%p), SimpleMesh(%p)", con, (RsSimpleMesh)s);
+    rsSimpleMeshDestroy((RsSimpleMesh)s);
+}
+
+static jint
+nSimpleMeshCreate(JNIEnv *_env, jobject _this, jint batchID, jint indexID, jintArray vtxIDs, jint primID)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    jint len = _env->GetArrayLength(vtxIDs);
+    LOG_API("nSimpleMeshCreate, con(%p), batchID(%i), indexID(%i), vtxIDs.len(%i), primID(%i)",
+            con, batchID, indexID, len, primID);
+    jint *ptr = _env->GetIntArrayElements(vtxIDs, NULL);
+    int id = (int)rsSimpleMeshCreate((void *)batchID, (void *)indexID, (void **)ptr, len, primID);
+    _env->ReleaseIntArrayElements(vtxIDs, ptr, 0/*JNI_ABORT*/);
+    return id;
+}
+
+static void
+nSimpleMeshBindVertex(JNIEnv *_env, jobject _this, jint s, jint alloc, jint slot)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nSimpleMeshBindVertex, con(%p), SimpleMesh(%p), Alloc(%p), slot(%i)", con, (RsSimpleMesh)s, (RsAllocation)alloc, slot);
+    rsSimpleMeshBindVertex((RsSimpleMesh)s, (RsAllocation)alloc, slot);
+}
+
+static void
+nSimpleMeshBindIndex(JNIEnv *_env, jobject _this, jint s, jint alloc)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nSimpleMeshBindIndex, con(%p), SimpleMesh(%p), Alloc(%p)", con, (RsSimpleMesh)s, (RsAllocation)alloc);
+    rsSimpleMeshBindIndex((RsSimpleMesh)s, (RsAllocation)alloc);
+}
+
+// ---------------------------------------------------------------------------
+
 
 static const char *classPathName = "android/renderscript/RenderScript";
 
@@ -1202,6 +1241,11 @@
 {"nSamplerSet",                    "(II)V",                                (void*)nSamplerSet },
 {"nSamplerCreate",                 "()I",                                  (void*)nSamplerCreate },
 
+{"nSimpleMeshDestroy",             "(I)V",                                 (void*)nSimpleMeshDestroy },
+{"nSimpleMeshCreate",              "(II[II)I",                             (void*)nSimpleMeshCreate },
+{"nSimpleMeshBindVertex",          "(III)V",                               (void*)nSimpleMeshBindVertex },
+{"nSimpleMeshBindIndex",           "(II)V",                                (void*)nSimpleMeshBindIndex },
+
 };
 
 static int registerFuncs(JNIEnv *_env)
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index 375cf6c..3234f39 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -99,6 +99,7 @@
 	rsScript.cpp \
 	rsScriptC.cpp \
 	rsScriptC_Lib.cpp \
+	rsSimpleMesh.cpp \
 	rsThreadIO.cpp \
 	rsType.cpp \
 	rsTriangleMesh.cpp
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index 1d14f70..d7d572e 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -25,7 +25,7 @@
 #endif
 
 //////////////////////////////////////////////////////
-// 
+//
 
 typedef void * RsAdapter1D;
 typedef void * RsAdapter2D;
@@ -38,6 +38,7 @@
 typedef void * RsScript;
 typedef void * RsScriptBasicTemp;
 typedef void * RsTriangleMesh;
+typedef void * RsSimpleMesh;
 typedef void * RsType;
 typedef void * RsLight;
 
@@ -51,6 +52,8 @@
 RsContext rsContextCreate(RsDevice, void *, uint32_t version);
 void rsContextDestroy(RsContext);
 
+#define RS_MAX_TEXTURE 2
+
 enum RsDataType {
     RS_TYPE_FLOAT,
     RS_TYPE_UNSIGNED,
@@ -59,22 +62,22 @@
 
 enum RsDataKind {
     RS_KIND_USER,
-    RS_KIND_RED, 
-    RS_KIND_GREEN, 
-    RS_KIND_BLUE, 
-    RS_KIND_ALPHA, 
-    RS_KIND_LUMINANCE, 
+    RS_KIND_RED,
+    RS_KIND_GREEN,
+    RS_KIND_BLUE,
+    RS_KIND_ALPHA,
+    RS_KIND_LUMINANCE,
     RS_KIND_INTENSITY,
-    RS_KIND_X, 
-    RS_KIND_Y, 
-    RS_KIND_Z, 
+    RS_KIND_X,
+    RS_KIND_Y,
+    RS_KIND_Z,
     RS_KIND_W,
-    RS_KIND_S, 
-    RS_KIND_T, 
-    RS_KIND_Q, 
+    RS_KIND_S,
+    RS_KIND_T,
+    RS_KIND_Q,
     RS_KIND_R,
-    RS_KIND_NX, 
-    RS_KIND_NY, 
+    RS_KIND_NX,
+    RS_KIND_NY,
     RS_KIND_NZ,
     RS_KIND_INDEX
 };
@@ -86,7 +89,7 @@
     RS_ELEMENT_USER_I16,
     RS_ELEMENT_USER_U32,
     RS_ELEMENT_USER_I32,
-    RS_ELEMENT_USER_FLOAT, 
+    RS_ELEMENT_USER_FLOAT,
 
     RS_ELEMENT_A_8,          // 7
     RS_ELEMENT_RGB_565,      // 8
@@ -96,14 +99,14 @@
     RS_ELEMENT_RGBA_8888,    // 12
 
     RS_ELEMENT_INDEX_16, //13
-    RS_ELEMENT_INDEX_32, 
-    RS_ELEMENT_XY_F32, 
-    RS_ELEMENT_XYZ_F32, 
-    RS_ELEMENT_ST_XY_F32, 
-    RS_ELEMENT_ST_XYZ_F32, 
+    RS_ELEMENT_INDEX_32,
+    RS_ELEMENT_XY_F32,
+    RS_ELEMENT_XYZ_F32,
+    RS_ELEMENT_ST_XY_F32,
+    RS_ELEMENT_ST_XYZ_F32,
     RS_ELEMENT_NORM_XYZ_F32,
     RS_ELEMENT_NORM_ST_XYZ_F32,
-};  
+};
 
 enum RsSamplerParam {
     RS_SAMPLER_MIN_FILTER,
@@ -111,7 +114,7 @@
     RS_SAMPLER_WRAP_S,
     RS_SAMPLER_WRAP_T,
     RS_SAMPLER_WRAP_R
-};  
+};
 
 enum RsSamplerValue {
     RS_SAMPLER_NEAREST,
@@ -119,7 +122,7 @@
     RS_SAMPLER_LINEAR_MIP_LINEAR,
     RS_SAMPLER_WRAP,
     RS_SAMPLER_CLAMP
-};  
+};
 
 enum RsDimension {
     RS_DIMENSION_X,
@@ -128,9 +131,9 @@
     RS_DIMENSION_LOD,
     RS_DIMENSION_FACE,
 
-    RS_DIMENSION_ARRAY_0 = 100, 
-    RS_DIMENSION_ARRAY_1, 
-    RS_DIMENSION_ARRAY_2, 
+    RS_DIMENSION_ARRAY_0 = 100,
+    RS_DIMENSION_ARRAY_1,
+    RS_DIMENSION_ARRAY_2,
     RS_DIMENSION_ARRAY_3,
     RS_DIMENSION_MAX = RS_DIMENSION_ARRAY_3
 };
diff --git a/libs/rs/RenderScriptEnv.h b/libs/rs/RenderScriptEnv.h
index 7a5556e..5eb8912 100644
--- a/libs/rs/RenderScriptEnv.h
+++ b/libs/rs/RenderScriptEnv.h
@@ -11,6 +11,7 @@
 typedef void * RsScript;
 typedef void * RsScriptBasicTemp;
 typedef void * RsTriangleMesh;
+typedef void * RsSimpleMesh;
 typedef void * RsType;
 typedef void * RsProgramFragment;
 typedef void * RsProgramFragmentStore;
diff --git a/libs/rs/java/Fountain/res/raw/fountain.c b/libs/rs/java/Fountain/res/raw/fountain.c
index 99551fcd..bf83aab 100644
--- a/libs/rs/java/Fountain/res/raw/fountain.c
+++ b/libs/rs/java/Fountain/res/raw/fountain.c
@@ -12,8 +12,9 @@
     int ct, ct2;
     int newPart;
     int drawCount;
-    int dx, dy, idx;
-    int posx,posy;
+    int idx;
+    float dx, dy;
+    float posx,posy;
     int c;
     int srcIdx;
     int dstIdx;
@@ -37,15 +38,15 @@
     if (touch) {
         newPart = loadI32(2, 0);
         for (ct2=0; ct2<rate; ct2++) {
-            dx = (int)((randf(1.f) - 0.5f) * 0x10000);
-            dy = (int)((randf(1.f) - 0.5f) * 0x10000);
+            dx = randf(1.f) - 0.5f;
+            dy = randf(1.f) - 0.5f;
 
             idx = newPart * 5 + 1;
-            storeI32(2, idx, dx);
-            storeI32(2, idx + 1, dy);
+            storeF(2, idx, dx);
+            storeF(2, idx + 1, dy);
             storeI32(2, idx + 2, maxLife);
-            storeI32(2, idx + 3, x << 16);
-            storeI32(2, idx + 4, y << 16);
+            storeF(2, idx + 3, x);
+            storeF(2, idx + 4, y);
 
             newPart++;
             if (newPart >= count) {
@@ -59,48 +60,50 @@
     for (ct=0; ct < count; ct++) {
         srcIdx = ct * 5 + 1;
 
-        dx = loadI32(2, srcIdx);
-        dy = loadI32(2, srcIdx + 1);
+        dx = loadF(2, srcIdx);
+        dy = loadF(2, srcIdx + 1);
         life = loadI32(2, srcIdx + 2);
-        posx = loadI32(2, srcIdx + 3);
-        posy = loadI32(2, srcIdx + 4);
+        posx = loadF(2, srcIdx + 3);
+        posy = loadF(2, srcIdx + 4);
 
         if (life) {
-            if (posy < (480 << 16)) {
+            if (posy < 480.f) {
                 dstIdx = drawCount * 9;
                 c = 0xffafcf | ((life >> lifeShift) << 24);
 
                 storeI32(1, dstIdx, c);
-                storeI32(1, dstIdx + 1, posx);
-                storeI32(1, dstIdx + 2, posy);
+                storeF(1, dstIdx + 1, posx);
+                storeF(1, dstIdx + 2, posy);
 
                 storeI32(1, dstIdx + 3, c);
-                storeI32(1, dstIdx + 4, posx + 0x10000);
-                storeI32(1, dstIdx + 5, posy + dy * 4);
+                storeF(1, dstIdx + 4, posx + 1.f);
+                storeF(1, dstIdx + 5, posy + dy);
 
                 storeI32(1, dstIdx + 6, c);
-                storeI32(1, dstIdx + 7, posx - 0x10000);
-                storeI32(1, dstIdx + 8, posy + dy * 4);
+                storeF(1, dstIdx + 7, posx - 1.f);
+                storeF(1, dstIdx + 8, posy + dy);
                 drawCount ++;
             } else {
                 if (dy > 0) {
-                    dy = (-dy) >> 1;
+                    dy *= -0.5f;
                 }
             }
 
             posx = posx + dx;
             posy = posy + dy;
-            dy = dy + 0x400;
+            dy = dy + 0.1f;
             life --;
 
             //storeI32(2, srcIdx, dx);
-            storeI32(2, srcIdx + 1, dy);
+            storeF(2, srcIdx + 1, dy);
             storeI32(2, srcIdx + 2, life);
-            storeI32(2, srcIdx + 3, posx);
-            storeI32(2, srcIdx + 4, posy);
+            storeF(2, srcIdx + 3, posx);
+            storeF(2, srcIdx + 4, posy);
         }
     }
 
-    drawTriangleArray(NAMED_PartBuffer, drawCount);
+    //drawTriangleArray(NAMED_PartBuffer, drawCount);
+    uploadToBufferObject(NAMED_PartBuffer);
+    drawSimpleMeshRange(NAMED_PartMesh, 0, drawCount * 3);
     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 4826879..c2d1c65 100644
--- a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
+++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
@@ -33,6 +33,10 @@
 import android.renderscript.ScriptC;
 import android.renderscript.ProgramFragment;
 import android.renderscript.ProgramStore;
+import android.renderscript.SimpleMesh;
+import android.renderscript.Type;
+import android.renderscript.Primitive;
+
 
 public class FountainRS {
 
@@ -64,6 +68,7 @@
     private Script mScript;
     private ProgramStore mPFS;
     private ProgramFragment mPF;
+    private SimpleMesh mSM;
 
     private Bitmap mBackground;
 
@@ -73,8 +78,6 @@
         int partCount = 1024;
 
         mIntAlloc = Allocation.createSized(mRS, Element.USER_I32, 10);
-        mPartAlloc = Allocation.createSized(mRS, Element.USER_I32, partCount * 3 * 3);
-        mPartAlloc.setName("PartBuffer");
         mVertAlloc = Allocation.createSized(mRS, Element.USER_I32, partCount * 5 + 1);
 
         ProgramStore.Builder bs = new ProgramStore.Builder(mRS, null, null);
@@ -96,12 +99,27 @@
         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);
+        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);
+        Element primElement = eb.create();
 
+        SimpleMesh.Builder smb = new SimpleMesh.Builder(mRS);
+        int vtxSlot = smb.addVertexType(primElement, partCount * 3);
+        smb.setPrimitive(Primitive.TRIANGLE);
+        mSM = smb.create();
+        mSM.setName("PartMesh");
+
+        mPartAlloc = mSM.createVertexAllocation(vtxSlot);
+        mPartAlloc.setName("PartBuffer");
+        mSM.bindVertexAllocation(mPartAlloc, 0);
+
+        // All setup of named objects should be done by this point
+        // because we are about to compile the script.
         ScriptC.Builder sb = new ScriptC.Builder(mRS);
         sb.setScript(mRes, R.raw.fountain);
         sb.setRoot(true);
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 05a8c37..e5d30e4 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -460,3 +460,32 @@
 	}
 
 
+SimpleMeshCreate {
+	ret RsSimpleMesh
+	param RsAllocation prim
+	param RsAllocation index
+	param RsAllocation *vtx
+	param uint32_t vtxCount
+	param uint32_t primType
+	}
+
+SimpleMeshDestroy {
+	param RsSimpleMesh mesh
+	}
+
+SimpleMeshBindIndex {
+	param RsSimpleMesh mesh
+	param RsAllocation idx
+	}
+
+SimpleMeshBindPrimitive {
+	param RsSimpleMesh mesh
+	param RsAllocation prim
+	}
+
+SimpleMeshBindVertex {
+	param RsSimpleMesh mesh
+	param RsAllocation vtx
+	param uint32_t slot
+	}
+
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index ecfbf83..5ec73d7 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -41,11 +41,11 @@
     mBufferID = 0;
 
     mType.set(type);
+    rsAssert(type);
     mPtr = malloc(mType->getSizeBytes());
     if (!mPtr) {
         LOGE("Allocation::Allocation, alloc failure");
     }
-
 }
 
 Allocation::~Allocation()
@@ -114,6 +114,7 @@
     glBindBuffer(GL_ARRAY_BUFFER, 0);
 }
 
+
 void Allocation::data(const void *data)
 {
     memcpy(mPtr, data, mType->getSizeBytes());
diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h
index d0b91fd..eb1da69 100644
--- a/libs/rs/rsAllocation.h
+++ b/libs/rs/rsAllocation.h
@@ -23,7 +23,7 @@
 namespace android {
 namespace renderscript {
 
-    
+
 
 class Allocation : public ObjectBase
 {
@@ -55,11 +55,15 @@
 
     void data(const void *data);
     void subData(uint32_t xoff, uint32_t count, const void *data);
-    void subData(uint32_t xoff, uint32_t yoff, 
+    void subData(uint32_t xoff, uint32_t yoff,
                  uint32_t w, uint32_t h, const void *data);
     void subData(uint32_t xoff, uint32_t yoff, uint32_t zoff,
                  uint32_t w, uint32_t h, uint32_t d, const void *data);
 
+    void enableGLVertexBuffers() const;
+    void setupGLIndexBuffers() const;
+
+
 protected:
     ObjectBaseRef<const Type> mType;
     void * mPtr;
@@ -87,7 +91,6 @@
     // is allowed.
     bool mIsVertexBuffer;
     uint32_t mBufferID;
-
 };
 
 }
diff --git a/libs/rs/rsComponent.cpp b/libs/rs/rsComponent.cpp
index a931811..fde62a0 100644
--- a/libs/rs/rsComponent.cpp
+++ b/libs/rs/rsComponent.cpp
@@ -15,6 +15,7 @@
  */
 
 #include "rsComponent.h"
+#include <GLES/gl.h>
 
 using namespace android;
 using namespace android::renderscript;
@@ -29,7 +30,7 @@
 }
 
 Component::Component(
-    DataKind dk, DataType dt, 
+    DataKind dk, DataType dt,
     bool isNormalized, uint32_t bits)
 {
     mType = dt;
@@ -41,3 +42,37 @@
 Component::~Component()
 {
 }
+
+uint32_t Component::getGLType() const
+{
+    switch(mType) {
+    case RS_TYPE_FLOAT:
+        rsAssert(mBits == 32);
+        return GL_FLOAT;
+    case RS_TYPE_SIGNED:
+        switch(mBits) {
+        case 32:
+            return 0;//GL_INT;
+        case 16:
+            return GL_SHORT;
+        case 8:
+            return GL_BYTE;
+        }
+        break;
+    case RS_TYPE_UNSIGNED:
+        switch(mBits) {
+        case 32:
+            return 0;//GL_UNSIGNED_INT;
+        case 16:
+            return GL_UNSIGNED_SHORT;
+        case 8:
+            return GL_UNSIGNED_BYTE;
+        }
+        break;
+    }
+    //rsAssert(!"Bad type");
+    //LOGE("mType %i, mKind %i, mBits %i, mIsNormalized %i", mType, mKind, mBits, mIsNormalized);
+    return 0;
+}
+
+
diff --git a/libs/rs/rsComponent.h b/libs/rs/rsComponent.h
index e1b05850c..9db107f 100644
--- a/libs/rs/rsComponent.h
+++ b/libs/rs/rsComponent.h
@@ -52,6 +52,8 @@
     DataKind getKind() const {return mKind;}
     uint32_t getBits() const {return mBits;}
 
+    uint32_t getGLType() const;
+
 protected:
 
     DataType mType;
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index 1f8352c..5d41460 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -26,6 +26,7 @@
 #include "rsMatrix.h"
 #include "rsAllocation.h"
 #include "rsTriangleMesh.h"
+#include "rsSimpleMesh.h"
 #include "rsMesh.h"
 #include "rsDevice.h"
 #include "rsScriptC.h"
diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp
index 069a128..0c5cb18 100644
--- a/libs/rs/rsElement.cpp
+++ b/libs/rs/rsElement.cpp
@@ -348,7 +348,7 @@
 }
 
 /////////////////////////////////////////
-// 
+//
 
 namespace android {
 namespace renderscript {
@@ -378,7 +378,7 @@
         sec->initPredefined();
     }
 
-    if ((predef < 0) || 
+    if ((predef < 0) ||
         (static_cast<uint32_t>(predef) >= sec->mPredefinedList.size())) {
         LOGE("rsElementGetPredefined: Request for bad predefined type");
         // error
@@ -395,14 +395,17 @@
 {
     ElementState * sec = &rsc->mStateElement;
 
+    Component *c = new Component(static_cast<Component::DataKind>(dk),
+                                 static_cast<Component::DataType>(dt),
+                                 isNormalized,
+                                 bits);
+    sec->mComponentBuildList.add(c);
 }
 
 RsElement rsi_ElementCreate(Context *rsc)
 {
     ElementState * sec = &rsc->mStateElement;
-
     Element *se = new Element(sec->mComponentBuildList.size());
-    sec->mAllElements.add(se);
 
     for (size_t ct = 0; ct < se->getComponentCount(); ct++) {
         se->setComponent(ct, sec->mComponentBuildList[ct]);
@@ -415,15 +418,7 @@
 
 void rsi_ElementDestroy(Context *rsc, RsElement vse)
 {
-    ElementState * sec = &rsc->mStateElement;
     Element * se = static_cast<Element *>(vse);
-
-    for (size_t ct = 0; ct < sec->mAllElements.size(); ct++) {
-        if (sec->mAllElements[ct] == se) {
-            sec->mAllElements.removeAt(ct);
-            break;
-        }
-    }
     se->decRef();
 }
 
diff --git a/libs/rs/rsElement.h b/libs/rs/rsElement.h
index ea6fa8f..0918522 100644
--- a/libs/rs/rsElement.h
+++ b/libs/rs/rsElement.h
@@ -39,12 +39,12 @@
 
 
     size_t getSizeBits() const;
-    size_t getSizeBytes() const { 
-        return (getSizeBits() + 7) >> 3; 
+    size_t getSizeBytes() const {
+        return (getSizeBits() + 7) >> 3;
     }
 
     size_t getComponentOffsetBits(uint32_t componentNumber) const;
-    size_t getComponentOffsetBytes(uint32_t componentNumber) const { 
+    size_t getComponentOffsetBytes(uint32_t componentNumber) const {
         return (getComponentOffsetBits(componentNumber) + 7) >> 3;
     }
 
@@ -68,7 +68,6 @@
     ElementState();
     ~ElementState();
 
-    Vector<Element *> mAllElements;
     Vector<Component *> mComponentBuildList;
 
 
@@ -78,7 +77,7 @@
             mElement = NULL;
         }
         Predefined(RsElementPredefined en, Element *e) {
-            mEnum = en; 
+            mEnum = en;
             mElement = e;
         }
         RsElementPredefined mEnum;
@@ -87,7 +86,7 @@
     Vector<Predefined> mPredefinedList;
 
     void initPredefined();
-    
+
 };
 
 
diff --git a/libs/rs/rsObjectBase.cpp b/libs/rs/rsObjectBase.cpp
index 3219c39..6a5b7d8 100644
--- a/libs/rs/rsObjectBase.cpp
+++ b/libs/rs/rsObjectBase.cpp
@@ -27,6 +27,7 @@
 
 ObjectBase::~ObjectBase()
 {
+    //LOGV("~ObjectBase %p  ref %i", this, mRefCount);
     rsAssert(!mRefCount);
 }
 
diff --git a/libs/rs/rsProgramFragment.cpp b/libs/rs/rsProgramFragment.cpp
index ea507dc..a315658 100644
--- a/libs/rs/rsProgramFragment.cpp
+++ b/libs/rs/rsProgramFragment.cpp
@@ -196,19 +196,12 @@
 {
     ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
     pf->bindTexture(slot, static_cast<Allocation *>(a));
-    if (pf == rsc->getFragment()) {
-        //pf->setupGL();
-    }
 }
 
 void rsi_ProgramFragmentBindSampler(Context *rsc, RsProgramFragment vpf, uint32_t slot, RsSampler s)
 {
     ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
     pf->bindSampler(slot, static_cast<Sampler *>(s));
-
-    if (pf == rsc->getFragment()) {
-        //pf->setupGL();
-    }
 }
 
 void rsi_ProgramFragmentSetType(Context *rsc, uint32_t slot, RsType vt)
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index 87ddf58..ecd8373 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -89,10 +89,10 @@
     glBindBuffer(GL_ARRAY_BUFFER, tm->mBufferObjects[0]);
     glBufferData(GL_ARRAY_BUFFER, tm->mVertexDataSize, tm->mVertexData, GL_STATIC_DRAW);
     glBindBuffer(GL_ARRAY_BUFFER, 0);
-    
+
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tm->mBufferObjects[1]);
     glBufferData(GL_ELEMENT_ARRAY_BUFFER, tm->mIndexDataSize, tm->mIndexData, GL_STATIC_DRAW);
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);    
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 }
 
 static uint32_t SC_loadU32(uint32_t bank, uint32_t offset)
@@ -189,17 +189,17 @@
 
 static float SC_maxf(float a, float b)
 {
-    return a > b ? a : b; 
+    return a > b ? a : b;
 }
 
 static float SC_minf(float a, float b)
 {
-    return a < b ? a : b; 
+    return a < b ? a : b;
 }
 
 static float SC_sqrf(float v)
 {
-    return v * v; 
+    return v * v;
 }
 
 static int SC_sqr(int v)
@@ -211,7 +211,7 @@
 {
     float x = x2 - x1;
     float y = y2 - y1;
-    return sqrtf(x * x + y * y); 
+    return sqrtf(x * x + y * y);
 }
 
 static float SC_distf3(float x1, float y1, float z1, float x2, float y2, float z2)
@@ -219,7 +219,7 @@
     float x = x2 - x1;
     float y = y2 - y1;
     float z = z2 - z1;
-    return sqrtf(x * x + y * y + z * z); 
+    return sqrtf(x * x + y * y + z * z);
 }
 
 static float SC_magf2(float a, float b)
@@ -234,12 +234,12 @@
 
 static float SC_radf(float degrees)
 {
-    return degrees * DEG_TO_RAD; 
+    return degrees * DEG_TO_RAD;
 }
 
 static float SC_degf(float radians)
 {
-    return radians * RAD_TO_DEG; 
+    return radians * RAD_TO_DEG;
 }
 
 static float SC_lerpf(float start, float stop, float amount)
@@ -282,10 +282,10 @@
 static uint32_t SC_minute()
 {
     GET_TLS();
-    
+
     time_t rawtime;
     time(&rawtime);
-    
+
     if (sc->mEnviroment.mTimeZone) {
         struct tm timeinfo;
         localtime_tz(&rawtime, &timeinfo, sc->mEnviroment.mTimeZone);
@@ -295,15 +295,15 @@
         timeinfo = localtime(&rawtime);
         return timeinfo->tm_min;
     }
-}   
+}
 
 static uint32_t SC_hour()
 {
     GET_TLS();
-    
+
     time_t rawtime;
     time(&rawtime);
-    
+
     if (sc->mEnviroment.mTimeZone) {
         struct tm timeinfo;
         localtime_tz(&rawtime, &timeinfo, sc->mEnviroment.mTimeZone);
@@ -318,10 +318,10 @@
 static uint32_t SC_day()
 {
     GET_TLS();
-    
+
     time_t rawtime;
     time(&rawtime);
-    
+
     if (sc->mEnviroment.mTimeZone) {
         struct tm timeinfo;
         localtime_tz(&rawtime, &timeinfo, sc->mEnviroment.mTimeZone);
@@ -331,15 +331,15 @@
         timeinfo = localtime(&rawtime);
         return timeinfo->tm_mday;
     }
-}   
+}
 
 static uint32_t SC_month()
 {
     GET_TLS();
-    
+
     time_t rawtime;
     time(&rawtime);
-    
+
     if (sc->mEnviroment.mTimeZone) {
         struct tm timeinfo;
         localtime_tz(&rawtime, &timeinfo, sc->mEnviroment.mTimeZone);
@@ -349,15 +349,15 @@
         timeinfo = localtime(&rawtime);
         return timeinfo->tm_mon;
     }
-} 
+}
 
 static uint32_t SC_year()
 {
     GET_TLS();
-    
+
     time_t rawtime;
     time(&rawtime);
-    
+
     if (sc->mEnviroment.mTimeZone) {
         struct tm timeinfo;
         localtime_tz(&rawtime, &timeinfo, sc->mEnviroment.mTimeZone);
@@ -631,6 +631,23 @@
                 x1, y1, z);
 }
 
+static void SC_drawSimpleMesh(RsSimpleMesh vsm)
+{
+    GET_TLS();
+    SimpleMesh *sm = static_cast<SimpleMesh *>(vsm);
+    rsc->setupCheck();
+    sm->render();
+}
+
+static void SC_drawSimpleMeshRange(RsSimpleMesh vsm, uint32_t start, uint32_t len)
+{
+    GET_TLS();
+    SimpleMesh *sm = static_cast<SimpleMesh *>(vsm);
+    rsc->setupCheck();
+    sm->renderRange(start, len);
+}
+
+
 //////////////////////////////////////////////////////////////////////////////
 //
 //////////////////////////////////////////////////////////////////////////////
@@ -674,18 +691,18 @@
     float red = 0.0f;
     float green = 0.0f;
     float blue = 0.0f;
-    
+
     float x = h;
     float y = s;
     float z = b;
-    
+
     float hf = (x - (int) x) * 6.0f;
     int ihf = (int) hf;
     float f = hf - ihf;
     float pv = z * (1.0f - y);
     float qv = z * (1.0f - y * f);
     float tv = z * (1.0f - y * (1.0f - f));
-    
+
     switch (ihf) {
         case 0:         // Red is the dominant color
             red = z;
@@ -718,7 +735,7 @@
             blue = qv;
             break;
     }
-    
+
     glColor4f(red, green, blue, a);
 }
 
@@ -728,6 +745,12 @@
     rsi_AllocationUploadToTexture(rsc, va, baseMipLevel);
 }
 
+static void SC_uploadToBufferObject(RsAllocation va)
+{
+    GET_TLS();
+    rsi_AllocationUploadToBufferObject(rsc, va);
+}
+
 static void SC_ClearColor(float r, float g, float b, float a)
 {
     //LOGE("c %f %f %f %f", r, g, b, a);
@@ -932,6 +955,10 @@
         "void", "(int mesh, int start, int count)" },
     { "drawLine", (void *)&SC_drawLine,
         "void", "(float x1, float y1, float z1, float x2, float y2, float z2)" },
+    { "drawSimpleMesh", (void *)&SC_drawSimpleMesh,
+        "void", "(int ism)" },
+    { "drawSimpleMeshRange", (void *)&SC_drawSimpleMeshRange,
+        "void", "(int ism, int start, int len)" },
 
 
     // misc
@@ -954,6 +981,8 @@
 
     { "uploadToTexture", (void *)&SC_uploadToTexture,
         "void", "(int, int)" },
+    { "uploadToBufferObject", (void *)&SC_uploadToBufferObject,
+        "void", "(int)" },
 
 
     { "debugF", (void *)&SC_debugF,
diff --git a/libs/rs/rsSimpleMesh.cpp b/libs/rs/rsSimpleMesh.cpp
new file mode 100644
index 0000000..08e36ac
--- /dev/null
+++ b/libs/rs/rsSimpleMesh.cpp
@@ -0,0 +1,148 @@
+/*
+ * 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.
+ */
+
+#include "rsContext.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+SimpleMesh::SimpleMesh()
+{
+}
+
+SimpleMesh::~SimpleMesh()
+{
+}
+
+void SimpleMesh::render() const
+{
+    if (mPrimitiveType.get()) {
+        renderRange(0, mPrimitiveType->getDimX());
+        return;
+    }
+
+    if (mIndexType.get()) {
+        renderRange(0, mIndexType->getDimX());
+        return;
+    }
+
+    renderRange(0, mVertexTypes[0]->getDimX());
+}
+
+void SimpleMesh::renderRange(uint32_t start, uint32_t len) const
+{
+    if (len < 1) {
+        return;
+    }
+
+    glDisableClientState(GL_VERTEX_ARRAY);
+    glDisableClientState(GL_NORMAL_ARRAY);
+    glDisableClientState(GL_COLOR_ARRAY);
+    for (uint32_t ct=0; ct < RS_MAX_TEXTURE; ct++) {
+        glClientActiveTexture(GL_TEXTURE0 + ct);
+        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+    }
+    glClientActiveTexture(GL_TEXTURE0);
+
+    for (uint32_t ct=0; ct < mVertexTypeCount; ct++) {
+        glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffers[ct]->getBufferObjectID());
+        mVertexTypes[ct]->enableGLVertexBuffer();
+    }
+
+    if (mIndexType.get()) {
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer->getBufferObjectID());
+        glDrawElements(mGLPrimitive, len, GL_UNSIGNED_SHORT, (GLvoid *)(start * 2));
+    } else {
+        glDrawArrays(mGLPrimitive, start, len);
+    }
+}
+
+
+
+SimpleMeshContext::SimpleMeshContext()
+{
+}
+
+SimpleMeshContext::~SimpleMeshContext()
+{
+}
+
+
+namespace android {
+namespace renderscript {
+
+
+RsSimpleMesh rsi_SimpleMeshCreate(Context *rsc, RsType prim, RsType idx, RsType *vtx, uint32_t vtxCount, uint32_t primType)
+{
+    SimpleMesh *sm = new SimpleMesh();
+    sm->incRef();
+
+    sm->mIndexType.set((const Type *)idx);
+    sm->mPrimitiveType.set((const Type *)prim);
+
+    sm->mVertexTypeCount = vtxCount;
+    sm->mVertexTypes = new ObjectBaseRef<const Type>[vtxCount];
+    sm->mVertexBuffers = new ObjectBaseRef<Allocation>[vtxCount];
+    for (uint32_t ct=0; ct < vtxCount; ct++) {
+        sm->mVertexTypes[ct].set((const Type *)vtx[ct]);
+    }
+
+    sm->mPrimitive = (RsPrimitive)primType;
+    switch(sm->mPrimitive) {
+    case RS_PRIMITIVE_POINT:          sm->mGLPrimitive = GL_POINTS; break;
+    case RS_PRIMITIVE_LINE:           sm->mGLPrimitive = GL_LINES; break;
+    case RS_PRIMITIVE_LINE_STRIP:     sm->mGLPrimitive = GL_LINE_STRIP; break;
+    case RS_PRIMITIVE_TRIANGLE:       sm->mGLPrimitive = GL_TRIANGLES; break;
+    case RS_PRIMITIVE_TRIANGLE_STRIP: sm->mGLPrimitive = GL_TRIANGLE_STRIP; break;
+    case RS_PRIMITIVE_TRIANGLE_FAN:   sm->mGLPrimitive = GL_TRIANGLE_FAN; break;
+    }
+    return sm;
+}
+
+void rsi_SimpleMeshBindVertex(Context *rsc, RsSimpleMesh mv, RsAllocation va, uint32_t slot)
+{
+    SimpleMesh *sm = static_cast<SimpleMesh *>(mv);
+    rsAssert(slot < sm->mVertexTypeCount);
+
+    sm->mVertexBuffers[slot].set((Allocation *)va);
+}
+
+void rsi_SimpleMeshBindIndex(Context *rsc, RsSimpleMesh mv, RsAllocation va)
+{
+    SimpleMesh *sm = static_cast<SimpleMesh *>(mv);
+    sm->mIndexBuffer.set((Allocation *)va);
+}
+
+void rsi_SimpleMeshBindPrimitive(Context *rsc, RsSimpleMesh mv, RsAllocation va)
+{
+    SimpleMesh *sm = static_cast<SimpleMesh *>(mv);
+    sm->mPrimitiveBuffer.set((Allocation *)va);
+}
+
+void rsi_SimpleMeshDestroy(Context *rsc, RsSimpleMesh vtm)
+{
+    SimpleMesh * tm = static_cast<SimpleMesh *>(vtm);
+    tm->decRef();
+}
+
+
+
+
+}}
+
diff --git a/libs/rs/rsSimpleMesh.h b/libs/rs/rsSimpleMesh.h
new file mode 100644
index 0000000..03b6c2c
--- /dev/null
+++ b/libs/rs/rsSimpleMesh.h
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_RS_SIMPLE_MESH_H
+#define ANDROID_RS_SIMPLE_MESH_H
+
+
+#include "RenderScript.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+
+// An element is a group of Components that occupies one cell in a structure.
+class SimpleMesh : public ObjectBase
+{
+public:
+    SimpleMesh();
+    ~SimpleMesh();
+
+    ObjectBaseRef<const Type> mIndexType;
+    ObjectBaseRef<const Type> mPrimitiveType;
+    ObjectBaseRef<const Type> *mVertexTypes;
+    uint32_t mVertexTypeCount;
+
+    ObjectBaseRef<Allocation> mIndexBuffer;
+    ObjectBaseRef<Allocation> mPrimitiveBuffer;
+    ObjectBaseRef<Allocation> *mVertexBuffers;
+
+    RsPrimitive mPrimitive;
+    uint32_t mGLPrimitive;
+
+
+    void render() const;
+    void renderRange(uint32_t start, uint32_t len) const;
+
+
+protected:
+};
+
+class SimpleMeshContext
+{
+public:
+    SimpleMeshContext();
+    ~SimpleMeshContext();
+
+
+};
+
+
+}
+}
+#endif //ANDROID_RS_SIMPLE_MESH_H
+
diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp
index bbe9720..43c3bda 100644
--- a/libs/rs/rsType.cpp
+++ b/libs/rs/rsType.cpp
@@ -15,6 +15,7 @@
  */
 
 #include "rsContext.h"
+#include <GLES/gl.h>
 
 using namespace android;
 using namespace android::renderscript;
@@ -23,6 +24,7 @@
 {
     mLODs = 0;
     mLODCount = 0;
+    memset(&mGL, 0, sizeof(mGL));
     clear();
 }
 
@@ -102,6 +104,7 @@
     }
     mTotalSizeBytes = offset;
 
+    makeGLComponents();
 }
 
 uint32_t Type::getLODOffset(uint32_t lod, uint32_t x) const
@@ -126,8 +129,155 @@
 }
 
 
+void Type::makeGLComponents()
+{
+    uint32_t texNum = 0;
+    memset(&mGL, 0, sizeof(mGL));
+
+    for (uint32_t ct=0; ct < getElement()->getComponentCount(); ct++) {
+        const Component *c = getElement()->getComponent(ct);
+
+        switch(c->getKind()) {
+        case Component::X:
+            rsAssert(mGL.mVtx.size == 0);
+            mGL.mVtx.size = 1;
+            mGL.mVtx.offset = mElement->getComponentOffsetBytes(ct);
+            mGL.mVtx.type = c->getGLType();
+            break;
+        case Component::Y:
+            rsAssert(mGL.mVtx.size == 1);
+            rsAssert(mGL.mVtx.type == c->getGLType());
+            mGL.mVtx.size = 2;
+            break;
+        case Component::Z:
+            rsAssert(mGL.mVtx.size == 2);
+            rsAssert(mGL.mVtx.type == c->getGLType());
+            mGL.mVtx.size = 3;
+            break;
+        case Component::W:
+            rsAssert(mGL.mVtx.size == 4);
+            rsAssert(mGL.mVtx.type == c->getGLType());
+            mGL.mVtx.size = 4;
+        break;
+
+        case Component::RED:
+            rsAssert(mGL.mColor.size == 0);
+            mGL.mColor.size = 1;
+            mGL.mColor.offset = mElement->getComponentOffsetBytes(ct);
+            mGL.mColor.type = c->getGLType();
+            break;
+        case Component::GREEN:
+            rsAssert(mGL.mColor.size == 1);
+            rsAssert(mGL.mColor.type == c->getGLType());
+            mGL.mColor.size = 2;
+            break;
+        case Component::BLUE:
+            rsAssert(mGL.mColor.size == 2);
+            rsAssert(mGL.mColor.type == c->getGLType());
+            mGL.mColor.size = 3;
+            break;
+        case Component::ALPHA:
+            rsAssert(mGL.mColor.size == 3);
+            rsAssert(mGL.mColor.type == c->getGLType());
+            mGL.mColor.size = 4;
+        break;
+
+        case Component::NX:
+            rsAssert(mGL.mNorm.size == 0);
+            mGL.mNorm.size = 1;
+            mGL.mNorm.offset = mElement->getComponentOffsetBytes(ct);
+            mGL.mNorm.type = c->getGLType();
+        break;
+        case Component::NY:
+            rsAssert(mGL.mNorm.size == 1);
+            rsAssert(mGL.mNorm.type == c->getGLType());
+            mGL.mNorm.size = 2;
+        break;
+        case Component::NZ:
+            rsAssert(mGL.mNorm.size == 2);
+            rsAssert(mGL.mNorm.type == c->getGLType());
+            mGL.mNorm.size = 3;
+        break;
+
+        case Component::S:
+            if (mGL.mTex[texNum].size) {
+                texNum++;
+            }
+            mGL.mTex[texNum].size = 1;
+            mGL.mTex[texNum].offset = mElement->getComponentOffsetBytes(ct);
+            mGL.mTex[texNum].type = c->getGLType();
+        break;
+        case Component::T:
+            rsAssert(mGL.mTex[texNum].size == 1);
+            rsAssert(mGL.mTex[texNum].type == c->getGLType());
+            mGL.mTex[texNum].size = 2;
+        break;
+        case Component::R:
+            rsAssert(mGL.mTex[texNum].size == 2);
+            rsAssert(mGL.mTex[texNum].type == c->getGLType());
+            mGL.mTex[texNum].size = 3;
+        break;
+        case Component::Q:
+            rsAssert(mGL.mTex[texNum].size == 3);
+            rsAssert(mGL.mTex[texNum].type == c->getGLType());
+            mGL.mTex[texNum].size = 4;
+        break;
+
+        default:
+            break;
+        }
+    }
+}
+
+void Type::enableGLVertexBuffer() const
+{
+    // Note: We are only going to enable buffers and never disable them
+    // here.  The reasonis more than one Allocation may be used as a vertex
+    // source.  So we cannot disable arrays that may have been in use by
+    // another allocation.
+
+    uint32_t stride = mElement->getSizeBytes();
+    if (mGL.mVtx.size) {
+        glEnableClientState(GL_VERTEX_ARRAY);
+        glVertexPointer(mGL.mVtx.size,
+                        mGL.mVtx.type,
+                        stride,
+                        (void *)mGL.mVtx.offset);
+    }
+
+    if (mGL.mNorm.size) {
+        glEnableClientState(GL_NORMAL_ARRAY);
+        rsAssert(mGL.mNorm.size == 3);
+        glNormalPointer(mGL.mNorm.size,
+                        stride,
+                        (void *)mGL.mNorm.offset);
+    }
+
+    if (mGL.mColor.size) {
+        glEnableClientState(GL_COLOR_ARRAY);
+        glColorPointer(mGL.mColor.size,
+                       mGL.mColor.type,
+                       stride,
+                       (void *)mGL.mColor.offset);
+    }
+
+    for (uint32_t ct=0; ct < RS_MAX_TEXTURE; ct++) {
+        if (mGL.mTex[ct].size) {
+            glClientActiveTexture(GL_TEXTURE0 + ct);
+            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+            glTexCoordPointer(mGL.mTex[ct].size,
+                              mGL.mTex[ct].type,
+                              stride,
+                              (void *)mGL.mTex[ct].offset);
+        }
+    }
+    glClientActiveTexture(GL_TEXTURE0);
+
+}
+
+
 //////////////////////////////////////////////////
-// 
+//
 namespace android {
 namespace renderscript {
 
@@ -190,6 +340,7 @@
     TypeState * stc = &rsc->mStateType;
 
     Type * st = new Type();
+    st->incRef();
     st->setDimX(stc->mX);
     st->setDimY(stc->mY);
     st->setDimZ(stc->mZ);
@@ -198,23 +349,13 @@
     st->setDimFaces(stc->mFaces);
     st->compute();
 
-    stc->mAllTypes.add(st);
-
     return st;
 }
 
 void rsi_TypeDestroy(Context *rsc, RsType vst)
 {
-    TypeState * stc = &rsc->mStateType;
     Type * st = static_cast<Type *>(vst);
-
-    for (size_t ct = 0; ct < stc->mAllTypes.size(); ct++) {
-        if (stc->mAllTypes[ct] == st) {
-            stc->mAllTypes.removeAt(ct);
-            break;
-        }
-    }
-    delete st;
+    st->decRef();
 }
 
 }
diff --git a/libs/rs/rsType.h b/libs/rs/rsType.h
index a717893..60d75d7 100644
--- a/libs/rs/rsType.h
+++ b/libs/rs/rsType.h
@@ -23,7 +23,7 @@
 namespace android {
 namespace renderscript {
 
-    
+
 class Type : public ObjectBase
 {
 public:
@@ -67,6 +67,8 @@
     void clear();
     void compute();
 
+    void enableGLVertexBuffer() const;
+
 
 protected:
     struct LOD {
@@ -94,7 +96,7 @@
     bool mDimLOD;
     bool mFaces;
 
-    // A list of array dimensions.  The count is the number of array dimensions and the 
+    // A list of array dimensions.  The count is the number of array dimensions and the
     // sizes is a per array size.
     //Vector<size_t> mDimArraysSizes;
 
@@ -105,6 +107,21 @@
     LOD *mLODs;
     uint32_t mLODCount;
 
+    struct VertexComponent_t {
+        uint32_t offset;
+        uint32_t type;
+        uint32_t size;
+        uint32_t stride;
+    };
+    struct GLState_t {
+        VertexComponent_t mVtx;
+        VertexComponent_t mNorm;
+        VertexComponent_t mColor;
+        VertexComponent_t mTex[RS_MAX_TEXTURE];
+    };
+    GLState_t mGL;
+    void makeGLComponents();
+
 private:
     Type(const Type &);
 };
@@ -115,8 +132,6 @@
     TypeState();
     ~TypeState();
 
-    Vector<Type *> mAllTypes;
-
     size_t mX;
     size_t mY;
     size_t mZ;
@@ -124,8 +139,11 @@
     bool mFaces;
     ObjectBaseRef<const Element> mElement;
 
+    ObjectBaseRef<const Type> mIndexType;
+    ObjectBaseRef<const Type> mPrimitiveType;
+    ObjectBaseRef<const Type> *mVertexTypes;
 
-    
+
 };