Begin implementing SimpleMesh and fix some bugs with refcounting and java object destruction tracking.
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 e1b0585..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;
 
-    
+
 };