Remove useless slot from ProgramVertex.  Optimize GL state setup.
diff --git a/java/Fall/src/com/android/fall/rs/FallRS.java b/java/Fall/src/com/android/fall/rs/FallRS.java
index ef875fc..833bed0 100644
--- a/java/Fall/src/com/android/fall/rs/FallRS.java
+++ b/java/Fall/src/com/android/fall/rs/FallRS.java
@@ -21,6 +21,7 @@
 import android.renderscript.ScriptC;
 import android.renderscript.ProgramFragment;
 import android.renderscript.ProgramStore;
+import android.renderscript.ProgramVertex;
 import android.renderscript.Allocation;
 import android.renderscript.Sampler;
 import android.renderscript.ProgramVertex;
@@ -79,7 +80,7 @@
         mResources = res;
         initRS();
     }
-    
+
     public void destroy() {
         mScript.destroy();
         mSampler.destroy();
@@ -126,7 +127,7 @@
     }
 
     private void createMesh() {
-        
+
     }
 
     private void createScriptStructures() {
@@ -210,7 +211,7 @@
         ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null);
         pvb.setTextureMatrixEnable(true);
         mPvBackground = pvb.create();
-        mPvBackground.bindAllocation(0, mPvOrthoAlloc);
+        mPvBackground.bindAllocation(mPvOrthoAlloc);
         mPvBackground.setName("PVBackground");
     }
 }
diff --git a/java/Film/src/com/android/film/FilmRS.java b/java/Film/src/com/android/film/FilmRS.java
index e598e0c..74f88c4 100644
--- a/java/Film/src/com/android/film/FilmRS.java
+++ b/java/Film/src/com/android/film/FilmRS.java
@@ -240,8 +240,8 @@
         initState();
 
         mPVA = new ProgramVertex.MatrixAllocation(mRS);
-        mPVBackground.bindAllocation(0, mPVA);
-        mPVImages.bindAllocation(0, mPVA);
+        mPVBackground.bindAllocation(mPVA);
+        mPVImages.bindAllocation(mPVA);
         mPVA.setupProjectionNormalized(320, 480);
 
 
diff --git a/java/Grass/src/com/android/grass/rs/GrassRS.java b/java/Grass/src/com/android/grass/rs/GrassRS.java
index 4ff7365..8160a41 100644
--- a/java/Grass/src/com/android/grass/rs/GrassRS.java
+++ b/java/Grass/src/com/android/grass/rs/GrassRS.java
@@ -265,7 +265,7 @@
         ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null);
         pvb.setTextureMatrixEnable(true);
         mPvBackground = pvb.create();
-        mPvBackground.bindAllocation(0, mPvOrthoAlloc);
+        mPvBackground.bindAllocation(mPvOrthoAlloc);
         mPvBackground.setName("PVBackground");
     }
 }
diff --git a/java/Rollo/src/com/android/rollo/RolloRS.java b/java/Rollo/src/com/android/rollo/RolloRS.java
index f6cf419..32a8f3c 100644
--- a/java/Rollo/src/com/android/rollo/RolloRS.java
+++ b/java/Rollo/src/com/android/rollo/RolloRS.java
@@ -168,7 +168,7 @@
         ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null);
         mPV = pvb.create();
         mPV.setName("PV");
-        mPV.bindAllocation(0, mPVAlloc);
+        mPV.bindAllocation(mPVAlloc);
 
         mPVOrthoAlloc = new ProgramVertex.MatrixAllocation(mRS);
         mPVOrthoAlloc.setupOrthoWindow(mWidth, mHeight);
@@ -176,7 +176,7 @@
         pvb.setTextureMatrixEnable(true);
         mPVOrtho = pvb.create();
         mPVOrtho.setName("PVOrtho");
-        mPVOrtho.bindAllocation(0, mPVOrthoAlloc);
+        mPVOrtho.bindAllocation(mPVOrthoAlloc);
 
         mRS.contextBindProgramVertex(mPV);
 
diff --git a/rs.spec b/rs.spec
index e118ace..05a8c37 100644
--- a/rs.spec
+++ b/rs.spec
@@ -409,15 +409,9 @@
 
 ProgramVertexBindAllocation {
 	param RsProgramVertex vpgm
-	param uint32_t slot
 	param RsAllocation constants
 	}
 
-ProgramVertexSetType {
-	param uint32_t slot
-	param RsType constants
-	}
-
 ProgramVertexSetTextureMatrixEnable {
 	param bool enable
 	}
diff --git a/rsAllocation.cpp b/rsAllocation.cpp
index ca277ef..ecfbf83 100644
--- a/rsAllocation.cpp
+++ b/rsAllocation.cpp
@@ -501,23 +501,25 @@
     return texAlloc;
 }
 
-
 void rsi_AllocationData(Context *rsc, RsAllocation va, const void *data)
 {
     Allocation *a = static_cast<Allocation *>(va);
     a->data(data);
+    rsc->allocationCheck(a);
 }
 
 void rsi_Allocation1DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t count, const void *data)
 {
     Allocation *a = static_cast<Allocation *>(va);
     a->subData(xoff, count, data);
+    rsc->allocationCheck(a);
 }
 
 void rsi_Allocation2DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data)
 {
     Allocation *a = static_cast<Allocation *>(va);
     a->subData(xoff, yoff, w, h, data);
+    rsc->allocationCheck(a);
 }
 
 
diff --git a/rsContext.cpp b/rsContext.cpp
index e52b0e0..46bd892 100644
--- a/rsContext.cpp
+++ b/rsContext.cpp
@@ -85,10 +85,15 @@
 
 bool Context::runRootScript()
 {
+#if RS_LOG_TIMES
+    struct timespec beginTime;
+    clock_gettime(CLOCK_MONOTONIC, &beginTime);
+#endif
+
     rsAssert(mRootScript->mEnviroment.mIsRoot);
 
-    glColor4f(1,1,1,1);
-    glEnable(GL_LIGHT0);
+    //glColor4f(1,1,1,1);
+    //glEnable(GL_LIGHT0);
     glViewport(0, 0, mWidth, mHeight);
 
     glDepthMask(GL_TRUE);
@@ -102,19 +107,34 @@
     glClear(GL_COLOR_BUFFER_BIT);
     glClear(GL_DEPTH_BUFFER_BIT);
 
-    return runScript(mRootScript.get(), 0);
+#if RS_LOG_TIMES
+    struct timespec startTime;
+    clock_gettime(CLOCK_MONOTONIC, &startTime);
+#endif
+    bool ret = runScript(mRootScript.get(), 0);
+
+#if RS_LOG_TIMES
+    struct timespec endTime;
+    clock_gettime(CLOCK_MONOTONIC, &endTime);
+
+    int t1 = ((unsigned long)startTime.tv_nsec - (unsigned long)beginTime.tv_nsec) / 1000 / 1000;
+    int t2 = ((unsigned long)endTime.tv_nsec - (unsigned long)startTime.tv_nsec) / 1000 / 1000;
+    LOGE("times  %i,  %i", t1, t2);
+#endif
+
+    return ret;
 }
 
 void Context::setupCheck()
 {
     if (mFragmentStore.get()) {
-        mFragmentStore->setupGL();
+        mFragmentStore->setupGL(&mStateFragmentStore);
     }
     if (mFragment.get()) {
-        mFragment->setupGL();
+        mFragment->setupGL(&mStateFragment);
     }
     if (mVertex.get()) {
-        mVertex->setupGL();
+        mVertex->setupGL(&mStateVertex);
     }
 
 }
@@ -245,7 +265,6 @@
     } else {
         mFragmentStore.set(pfs);
     }
-    mFragmentStore->setupGL();
 }
 
 void Context::setFragment(ProgramFragment *pf)
@@ -255,7 +274,13 @@
     } else {
         mFragment.set(pf);
     }
-    mFragment->setupGL();
+}
+
+void Context::allocationCheck(const Allocation *a)
+{
+    mVertex->checkUpdatedAllocation(a);
+    mFragment->checkUpdatedAllocation(a);
+    mFragmentStore->checkUpdatedAllocation(a);
 }
 
 void Context::setVertex(ProgramVertex *pv)
@@ -265,7 +290,6 @@
     } else {
         mVertex.set(pv);
     }
-    mVertex->setupGL();
 }
 
 void Context::assignName(ObjectBase *obj, const char *name, uint32_t len)
diff --git a/rsContext.h b/rsContext.h
index a00b8e8..1f8352c 100644
--- a/rsContext.h
+++ b/rsContext.h
@@ -45,7 +45,7 @@
 namespace android {
 namespace renderscript {
 
-class Context 
+class Context
 {
 public:
     Context(Device *, Surface *);
@@ -86,6 +86,7 @@
     const ProgramVertex * getVertex() {return mVertex.get();}
 
     void setupCheck();
+    void allocationCheck(const Allocation *);
 
     void assignName(ObjectBase *obj, const char *name, uint32_t len);
     void removeName(ObjectBase *obj);
diff --git a/rsProgram.cpp b/rsProgram.cpp
index 5a83fb7..6606daa 100644
--- a/rsProgram.cpp
+++ b/rsProgram.cpp
@@ -34,12 +34,19 @@
 }
 
 
-void Program::setAllocation(Allocation *alloc)
+void Program::bindAllocation(Allocation *alloc)
 {
     mConstants.set(alloc);
     mDirty = true;
 }
 
+void Program::checkUpdatedAllocation(const Allocation *alloc)
+{
+    if (mConstants.get() == alloc) {
+        mDirty = true;
+    }
+}
+
 void Program::setupGL()
 {
 
diff --git a/rsProgram.h b/rsProgram.h
index 913fdd2..251072f 100644
--- a/rsProgram.h
+++ b/rsProgram.h
@@ -33,10 +33,12 @@
     virtual ~Program();
 
 
-    void setAllocation(Allocation *);
+    void bindAllocation(Allocation *);
 
     virtual void setupGL();
 
+    void checkUpdatedAllocation(const Allocation *);
+
 protected:
     // Components not listed in "in" will be passed though
     // unless overwritten by components in out.
@@ -45,8 +47,7 @@
 
     ObjectBaseRef<Allocation> mConstants;
 
-    bool mDirty;
-
+    mutable bool mDirty;
 };
 
 
diff --git a/rsProgramFragment.cpp b/rsProgramFragment.cpp
index 628f93e..ea507dc 100644
--- a/rsProgramFragment.cpp
+++ b/rsProgramFragment.cpp
@@ -39,8 +39,13 @@
 {
 }
 
-void ProgramFragment::setupGL()
+void ProgramFragment::setupGL(ProgramFragmentState *state)
 {
+    if ((state->mLast.get() == this) && !mDirty) {
+        return;
+    }
+    state->mLast.set(this);
+
     for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) {
         glActiveTexture(GL_TEXTURE0 + ct);
         if (!(mTextureEnableMask & (1 << ct)) || !mTextures[ct].get()) {
@@ -90,8 +95,8 @@
         }
     }
 
-
     glActiveTexture(GL_TEXTURE0);
+    mDirty = false;
 }
 
 
@@ -104,6 +109,7 @@
 
     //LOGE("bindtex %i %p", slot, a);
     mTextures[slot].set(a);
+    mDirty = true;
 }
 
 void ProgramFragment::bindSampler(uint32_t slot, Sampler *s)
@@ -114,6 +120,7 @@
     }
 
     mSamplers[slot].set(s);
+    mDirty = true;
 }
 
 void ProgramFragment::setType(uint32_t slot, const Element *e, uint32_t dim)
@@ -190,7 +197,7 @@
     ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
     pf->bindTexture(slot, static_cast<Allocation *>(a));
     if (pf == rsc->getFragment()) {
-        pf->setupGL();
+        //pf->setupGL();
     }
 }
 
@@ -200,7 +207,7 @@
     pf->bindSampler(slot, static_cast<Sampler *>(s));
 
     if (pf == rsc->getFragment()) {
-        pf->setupGL();
+        //pf->setupGL();
     }
 }
 
diff --git a/rsProgramFragment.h b/rsProgramFragment.h
index 896d8dd..57fb6a5 100644
--- a/rsProgramFragment.h
+++ b/rsProgramFragment.h
@@ -23,19 +23,19 @@
 namespace android {
 namespace renderscript {
 
+class ProgramFragmentState;
 
 class ProgramFragment : public Program
 {
 public:
     const static uint32_t MAX_TEXTURE = 2;
-    const static uint32_t MAX_CONSTANTS = 2;
 
 
 
     ProgramFragment(Element *in, Element *out);
     virtual ~ProgramFragment();
 
-    virtual void setupGL();
+    virtual void setupGL(ProgramFragmentState *);
 
 
 
@@ -53,7 +53,7 @@
     // Texture lookups go though a sampler which in effect converts normalized
     // coordinates into type specific.  Multiple samples may also be taken
     // and filtered.
-    // 
+    //
     // Constants are strictly accessed by programetic loads.
     ObjectBaseRef<Allocation> mTextures[MAX_TEXTURE];
     ObjectBaseRef<Sampler> mSamplers[MAX_TEXTURE];
@@ -61,21 +61,12 @@
     uint32_t mTextureDimensions[MAX_TEXTURE];
 
 
-    ObjectBaseRef<Allocation> mConstants[MAX_CONSTANTS];
-    ObjectBaseRef<Type> mConstantTypes[MAX_CONSTANTS];
-
-
     // Hacks to create a program for now
     RsTexEnvMode mEnvModes[MAX_TEXTURE];
     uint32_t mTextureEnableMask;
-
-
-
-
-
 };
 
-class ProgramFragmentState 
+class ProgramFragmentState
 {
 public:
     ProgramFragmentState();
@@ -87,6 +78,8 @@
     ObjectBaseRef<Type> mTextureTypes[ProgramFragment::MAX_TEXTURE];
     ObjectBaseRef<ProgramFragment> mDefault;
     Vector<ProgramFragment *> mPrograms;
+
+    ObjectBaseRef<ProgramFragment> mLast;
 };
 
 
diff --git a/rsProgramFragmentStore.cpp b/rsProgramFragmentStore.cpp
index 9ee270f..27f4015 100644
--- a/rsProgramFragmentStore.cpp
+++ b/rsProgramFragmentStore.cpp
@@ -48,8 +48,13 @@
 {
 }
 
-void ProgramFragmentStore::setupGL()
+void ProgramFragmentStore::setupGL(ProgramFragmentStoreState *state)
 {
+    if (state->mLast.get() == this) {
+        return;
+    }
+    state->mLast.set(this);
+
     glColorMask(mColorRWriteEnable,
                 mColorGWriteEnable,
                 mColorBWriteEnable,
@@ -123,7 +128,7 @@
 void ProgramFragmentStore::setBlendFunc(RsBlendSrcFunc src, RsBlendDstFunc dst)
 {
     mBlendEnable = true;
-    if ((src == RS_BLEND_SRC_ONE) && 
+    if ((src == RS_BLEND_SRC_ONE) &&
         (dst == RS_BLEND_DST_ZERO)) {
         mBlendEnable = false;
     }
diff --git a/rsProgramFragmentStore.h b/rsProgramFragmentStore.h
index bd3a9f4..0de5c3a 100644
--- a/rsProgramFragmentStore.h
+++ b/rsProgramFragmentStore.h
@@ -23,18 +23,15 @@
 namespace android {
 namespace renderscript {
 
+class ProgramFragmentStoreState;
 
 class ProgramFragmentStore : public Program
 {
 public:
-
-
-
     ProgramFragmentStore(Element *in, Element *out);
     virtual ~ProgramFragmentStore();
 
-    virtual void setupGL();
-
+    virtual void setupGL(ProgramFragmentStoreState *);
 
     void setDepthFunc(RsDepthFunc);
     void setDepthMask(bool);
@@ -55,21 +52,14 @@
     int32_t mBlendSrc;
     int32_t mBlendDst;
 
-
-
     bool mDepthTestEnable;
     bool mDepthWriteEnable;
     int32_t mDepthFunc;
 
-
-
     bool mStencilTestEnable;
-
-
-
 };
 
-class ProgramFragmentStoreState 
+class ProgramFragmentStoreState
 {
 public:
     ProgramFragmentStoreState();
@@ -77,6 +67,9 @@
     void init(Context *rsc, int32_t w, int32_t h);
 
     ObjectBaseRef<ProgramFragmentStore> mDefault;
+    ObjectBaseRef<ProgramFragmentStore> mLast;
+
+
     ProgramFragmentStore *mPFS;
 };
 
diff --git a/rsProgramVertex.cpp b/rsProgramVertex.cpp
index 792135d..c66e488 100644
--- a/rsProgramVertex.cpp
+++ b/rsProgramVertex.cpp
@@ -44,9 +44,14 @@
     LOGV("%6.2f, %6.2f, %6.2f, %6.2f", f[3], f[7], f[11], f[15]);
 }
 
-void ProgramVertex::setupGL()
+void ProgramVertex::setupGL(ProgramVertexState *state)
 {
-    const float *f = static_cast<const float *>(mConstants[0]->getPtr());
+    if ((state->mLast.get() == this) && !mDirty) {
+        return;
+    }
+    state->mLast.set(this);
+
+    const float *f = static_cast<const float *>(mConstants->getPtr());
 
     glMatrixMode(GL_TEXTURE);
     if (mTextureMatrixEnable) {
@@ -72,7 +77,7 @@
     } else {
         glDisable(GL_LIGHTING);
     }
-    
+
     if (!f) {
         LOGE("Must bind constants to vertex program");
     }
@@ -81,16 +86,8 @@
     glLoadMatrixf(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]);
     glMatrixMode(GL_MODELVIEW);
     glLoadMatrixf(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET]);
-}
 
-void ProgramVertex::setConstantType(uint32_t slot, const Type *t)
-{
-    mConstantTypes[slot].set(t);
-}
-
-void ProgramVertex::bindAllocation(uint32_t slot, Allocation *a)
-{
-    mConstants[slot].set(a);
+    mDirty = false;
 }
 
 void ProgramVertex::addLight(const Light *l)
@@ -103,20 +100,23 @@
 
 void ProgramVertex::setProjectionMatrix(const rsc_Matrix *m) const
 {
-    float *f = static_cast<float *>(mConstants[0]->getPtr());
+    float *f = static_cast<float *>(mConstants->getPtr());
     memcpy(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], m, sizeof(rsc_Matrix));
+    mDirty = true;
 }
 
 void ProgramVertex::setModelviewMatrix(const rsc_Matrix *m) const
 {
-    float *f = static_cast<float *>(mConstants[0]->getPtr());
+    float *f = static_cast<float *>(mConstants->getPtr());
     memcpy(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET], m, sizeof(rsc_Matrix));
+    mDirty = true;
 }
 
 void ProgramVertex::setTextureMatrix(const rsc_Matrix *m) const
 {
-    float *f = static_cast<float *>(mConstants[0]->getPtr());
+    float *f = static_cast<float *>(mConstants->getPtr());
     memcpy(&f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET], m, sizeof(rsc_Matrix));
+    mDirty = true;
 }
 
 
@@ -139,8 +139,8 @@
     mDefaultAlloc.set(alloc);
     mDefault.set(pv);
 
-    pv->bindAllocation(0, alloc);
-    
+    pv->bindAllocation(alloc);
+
     Matrix m;
     m.loadOrtho(0,w, h,0, -1,1);
     alloc->subData(RS_PROGRAM_VERTEX_PROJECTION_OFFSET, 16, &m.m[0]);
@@ -167,15 +167,10 @@
     return pv;
 }
 
-void rsi_ProgramVertexBindAllocation(Context *rsc, RsProgramVertex vpgm, uint32_t slot, RsAllocation constants)
+void rsi_ProgramVertexBindAllocation(Context *rsc, RsProgramVertex vpgm, RsAllocation constants)
 {
     ProgramVertex *pv = static_cast<ProgramVertex *>(vpgm);
-    pv->bindAllocation(slot, static_cast<Allocation *>(constants));
-}
-
-void rsi_ProgramVertexSetType(Context *rsc, uint32_t slot, RsType constants)
-{
-    rsc->mStateVertex.mPV->setConstantType(slot, static_cast<const Type *>(constants));
+    pv->bindAllocation(static_cast<Allocation *>(constants));
 }
 
 void rsi_ProgramVertexSetTextureMatrixEnable(Context *rsc, bool enable)
diff --git a/rsProgramVertex.h b/rsProgramVertex.h
index da5ed81..c9ce7aa 100644
--- a/rsProgramVertex.h
+++ b/rsProgramVertex.h
@@ -23,21 +23,19 @@
 namespace android {
 namespace renderscript {
 
+class ProgramVertexState;
 
 class ProgramVertex : public Program
 {
 public:
-    const static uint32_t MAX_CONSTANTS = 2;
     const static uint32_t MAX_LIGHTS = 8;
 
     ProgramVertex(Element *in, Element *out);
     virtual ~ProgramVertex();
 
-    virtual void setupGL();
+    virtual void setupGL(ProgramVertexState *state);
 
 
-    void setConstantType(uint32_t slot, const Type *);
-    void bindAllocation(uint32_t slot, Allocation *);
     void setTextureMatrixEnable(bool e) {mTextureMatrixEnable = e;}
     void addLight(const Light *);
 
@@ -46,21 +44,15 @@
     void setTextureMatrix(const rsc_Matrix *) const;
 
 protected:
-    bool mDirty;
     uint32_t mLightCount;
-
-    ObjectBaseRef<Allocation> mConstants[MAX_CONSTANTS];
-    ObjectBaseRef<const Type> mConstantTypes[MAX_CONSTANTS];
     ObjectBaseRef<const Light> mLights[MAX_LIGHTS];
 
-
     // Hacks to create a program for now
     bool mTextureMatrixEnable;
-
 };
 
 
-class ProgramVertexState 
+class ProgramVertexState
 {
 public:
     ProgramVertexState();
@@ -69,8 +61,9 @@
     void init(Context *rsc, int32_t w, int32_t h);
 
     ObjectBaseRef<ProgramVertex> mDefault;
+    ObjectBaseRef<ProgramVertex> mLast;
     ObjectBaseRef<Allocation> mDefaultAlloc;
-    
+
 
 
     ProgramVertex *mPV;
diff --git a/rsUtils.h b/rsUtils.h
index b13e88f..f0e4750 100644
--- a/rsUtils.h
+++ b/rsUtils.h
@@ -17,12 +17,13 @@
 #ifndef ANDROID_RS_UTILS_H
 #define ANDROID_RS_UTILS_H
 
-#define LOG_NDEBUG 0 
+#define LOG_NDEBUG 0
 #define LOG_TAG "rs"
 #include <utils/Log.h>
 #include <utils/Vector.h>
 #include <stdlib.h>
 #include <pthread.h>
+#include <time.h>
 
 #include <EGL/egl.h>
 #include <math.h>
@@ -38,6 +39,8 @@
 #define rsAssert(v) while(0)
 #endif
 
+#define RS_LOG_TIMES 0
+
 template<typename T>
 T rsMin(T in1, T in2)
 {