Add RS support for generic attribs as input to vertex programs.
diff --git a/rs.spec b/rs.spec
index d12431f..ac115d3 100644
--- a/rs.spec
+++ b/rs.spec
@@ -20,16 +20,6 @@
 	param RsProgramRaster pgm
 	}
 
-ContextSetDefineF {
-    param const char* name
-    param float value
-    }
-
-ContextSetDefineI32 {
-    param const char* name
-    param int32_t value
-    }
-
 ContextPause {
 	}
 
diff --git a/rsComponent.cpp b/rsComponent.cpp
index 0574343..15a56f7 100644
--- a/rsComponent.cpp
+++ b/rsComponent.cpp
@@ -264,6 +264,27 @@
     return s;
 }
 
+String8 Component::getGLSLType() const
+{
+    if (mType == RS_TYPE_SIGNED_32) {
+        switch(mVectorSize) {
+        case 1: return String8("int");
+        case 2: return String8("ivec2");
+        case 3: return String8("ivec3");
+        case 4: return String8("ivec4");
+        }
+    }
+    if (mType == RS_TYPE_FLOAT_32) {
+        switch(mVectorSize) {
+        case 1: return String8("float");
+        case 2: return String8("vec2");
+        case 3: return String8("vec3");
+        case 4: return String8("vec4");
+        }
+    }
+    return String8();
+}
+
 static const char * gTypeStrings[] = {
     "NONE",
     "F16",
diff --git a/rsComponent.h b/rsComponent.h
index c122c8e..71de324 100644
--- a/rsComponent.h
+++ b/rsComponent.h
@@ -36,6 +36,7 @@
     uint32_t getGLType() const;
     uint32_t getGLFormat() const;
     String8 getCType() const;
+    String8 getGLSLType() const;
     void dumpLOGV(const char *prefix) const;
 
 
diff --git a/rsContext.cpp b/rsContext.cpp
index 11f26b9..181902b 100644
--- a/rsContext.cpp
+++ b/rsContext.cpp
@@ -632,26 +632,6 @@
     }
 }
 
-void Context::appendVarDefines(String8 *str) const
-{
-    char buf[256];
-    for (size_t ct=0; ct < mInt32Defines.size(); ct++) {
-        str->append("#define ");
-        str->append(mInt32Defines.keyAt(ct));
-        str->append(" ");
-        sprintf(buf, "%i\n", (int)mInt32Defines.valueAt(ct));
-        str->append(buf);
-
-    }
-    for (size_t ct=0; ct < mFloatDefines.size(); ct++) {
-        str->append("#define ");
-        str->append(mFloatDefines.keyAt(ct));
-        str->append(" ");
-        sprintf(buf, "%ff\n", mFloatDefines.valueAt(ct));
-        str->append(buf);
-    }
-}
-
 bool Context::objDestroyOOBInit()
 {
     int status = pthread_mutex_init(&mObjDestroy.mMutex, NULL);
@@ -851,16 +831,6 @@
     ob->decUserRef();
 }
 
-void rsi_ContextSetDefineF(Context *rsc, const char* name, float value)
-{
-    rsc->addInt32Define(name, value);
-}
-
-void rsi_ContextSetDefineI32(Context *rsc, const char* name, int32_t value)
-{
-    rsc->addFloatDefine(name, value);
-}
-
 void rsi_ContextPause(Context *rsc)
 {
     rsc->pause();
diff --git a/rsContext.h b/rsContext.h
index aa7436d..2edd16d 100644
--- a/rsContext.h
+++ b/rsContext.h
@@ -105,7 +105,6 @@
     void removeName(ObjectBase *obj);
     ObjectBase * lookupName(const char *name) const;
     void appendNameDefines(String8 *str) const;
-    void appendVarDefines(String8 *str) const;
 
     uint32_t getMessageToClient(void *data, size_t *receiveLen, size_t bufferLen, bool wait);
     bool sendMessageToClient(void *data, uint32_t cmdID, size_t len, bool waitForSpace);
@@ -127,14 +126,6 @@
         return mStateRaster.mDefault.get();
     }
 
-    void addInt32Define(const char* name, int32_t value) {
-        mInt32Defines.add(String8(name), value);
-    }
-
-    void addFloatDefine(const char* name, float value) {
-        mFloatDefines.add(String8(name), value);
-    }
-
     uint32_t getWidth() const {return mEGL.mWidth;}
     uint32_t getHeight() const {return mEGL.mHeight;}
 
@@ -249,8 +240,6 @@
     Surface *mWndSurface;
 
     Vector<ObjectBase *> mNames;
-    KeyedVector<String8,int> mInt32Defines;
-    KeyedVector<String8,float> mFloatDefines;
 
     uint64_t mTimers[_RS_TIMER_TOTAL];
     Timers mTimerActive;
diff --git a/rsElement.cpp b/rsElement.cpp
index 9944c0e..207ad15 100644
--- a/rsElement.cpp
+++ b/rsElement.cpp
@@ -43,17 +43,6 @@
     mFields = NULL;
     mFieldCount = 0;
 }
-/*
-void Element::setComponent(uint32_t idx, Component *c)
-{
-    rsAssert(!mComponents[idx].get());
-    rsAssert(idx < mComponentCount);
-    mComponents[idx].set(c);
-
-// Fixme: This should probably not be here
-    c->incUserRef();
-}
-*/
 
 size_t Element::getSizeBits() const
 {
@@ -152,6 +141,24 @@
     return s;
 }
 
+String8 Element::getGLSLType(uint32_t indent) const
+{
+    String8 s;
+    for (uint32_t ct=0; ct < indent; ct++) {
+        s.append(" ");
+    }
+
+    if (!mFieldCount) {
+        // Basic component.
+        s.append(mComponent.getGLSLType());
+    } else {
+        rsAssert(0);
+        //s.append("struct ");
+        //s.append(getCStructBody(indent));
+    }
+
+    return s;
+}
 
 
 
@@ -194,58 +201,6 @@
     return e;
 }
 
-/*
-void rsi_ElementAdd(Context *rsc, RsDataKind dk, RsDataType dt, bool isNormalized, size_t bits, const char *name)
-{
-    ElementState * sec = &rsc->mStateElement;
-
-    rsAssert(bits > 0);
-
-    Element *c = Element::create(rsc, dk, dt, isNormalized, bits);
-    sec->mBuildList.add(c);
-    if (name)
-        sec->mNames.add(String8(name));
-    else
-        sec->mNames.add(String8(""));
-}
-
-RsElement rsi_ElementCreate(Context *rsc)
-{
-    ElementState * sec = &rsc->mStateElement;
-
-    size_t count = sec->mBuildList.size();
-    rsAssert(count > 0);
-
-    if (count == 1) {
-        Element *se = sec->mBuildList[0];
-        se->incUserRef();
-        sec->mBuildList.clear();
-        sec->mNames.clear();
-        return se;
-    }
-
-    Element ** tmpElements = (Element **)calloc(count, sizeof(Element *));
-    const char ** tmpNames = (const char **)calloc(count, sizeof(char *));
-    size_t * tmpLengths = (size_t *)calloc(count, sizeof(size_t));
-
-
-    for (size_t ct = 0; ct < count; ct++) {
-        tmpElements[ct] = sec->mBuildList[ct];
-        tmpNames[ct] = sec->mNames[ct].string();
-        tmpLengths[ct] = sec->mNames[ct].length();
-    }
-    Element *se = Element::create(rsc, tmpElements, tmpNames, tmpLengths, count);
-
-    sec->mBuildList.clear();
-    sec->mNames.clear();
-    se->incUserRef();
-    free(tmpElements);
-    free(tmpNames);
-    free(tmpLengths);
-    return se;
-}
-*/
-
 
 }
 }
diff --git a/rsElement.h b/rsElement.h
index c46922c..777e8ee 100644
--- a/rsElement.h
+++ b/rsElement.h
@@ -32,13 +32,9 @@
 public:
     ~Element();
 
-
-    //void setComponent(uint32_t idx, Component *c);
-
     uint32_t getGLType() const;
     uint32_t getGLFormat() const;
 
-
     size_t getSizeBits() const;
     size_t getSizeBytes() const {
         return (getSizeBits() + 7) >> 3;
@@ -55,13 +51,12 @@
 
     const Component & getComponent() const {return mComponent;}
     RsDataType getType() const {return mComponent.getType();}
-    //bool getIsNormalized() const {return mIsNormalized;}
     RsDataKind getKind() const {return mComponent.getKind();}
     uint32_t getBits() const {return mBits;}
-    //uint32_t getGLType() const;
 
     String8 getCType(uint32_t indent=0) const;
     String8 getCStructBody(uint32_t indent=0) const;
+    String8 getGLSLType(uint32_t indent=0) const;
 
     void dumpLOGV(const char *prefix) const;
 
@@ -94,8 +89,6 @@
     ElementState();
     ~ElementState();
 
-    Vector<Element *> mBuildList;
-    Vector<String8> mNames;
 };
 
 
diff --git a/rsProgram.cpp b/rsProgram.cpp
index ede8c86..b7639be 100644
--- a/rsProgram.cpp
+++ b/rsProgram.cpp
@@ -144,6 +144,42 @@
     mDirty = true;
 }
 
+String8 Program::getGLSLInputString() const
+{
+    String8 s;
+    for (uint32_t ct=0; ct < mInputCount; ct++) {
+        const Element *e = mInputElements[ct].get();
+        for (uint32_t field=0; field < e->getFieldCount(); field++) {
+            const Element *f = e->getField(field);
+
+            // Cannot be complex
+            rsAssert(!f->getFieldCount());
+            switch(f->getComponent().getVectorSize()) {
+            case 1: s.append("attribute float ATTRIB_"); break;
+            case 2: s.append("attribute vec2 ATTRIB_"); break;
+            case 3: s.append("attribute vec3 ATTRIB_"); break;
+            case 4: s.append("attribute vec4 ATTRIB_"); break;
+            default:
+                rsAssert(0);
+            }
+
+            s.append(e->getFieldName(field));
+            s.append(";\n");
+        }
+    }
+    return s;
+}
+
+String8 Program::getGLSLOutputString() const
+{
+    return String8();
+}
+
+String8 Program::getGLSLConstantString() const
+{
+    return String8();
+}
+
 
 void Program::createShader()
 {
diff --git a/rsProgram.h b/rsProgram.h
index 25a5434..dc3a57c 100644
--- a/rsProgram.h
+++ b/rsProgram.h
@@ -53,6 +53,10 @@
     const String8 & getAttribName(uint32_t i) const {return mAttribNames[i];}
     const String8 & getUniformName(uint32_t i) const {return mUniformNames[i];}
 
+    String8 getGLSLInputString() const;
+    String8 getGLSLOutputString() const;
+    String8 getGLSLConstantString() const;
+
 protected:
     // Components not listed in "in" will be passed though
     // unless overwritten by components in out.
diff --git a/rsProgramVertex.cpp b/rsProgramVertex.cpp
index fe628ca..b207558 100644
--- a/rsProgramVertex.cpp
+++ b/rsProgramVertex.cpp
@@ -116,12 +116,6 @@
 {
     mShader.setTo("");
 
-    for (uint32_t ct=0; ct < mAttribCount; ct++) {
-        mShader.append("attribute vec4 ");
-        mShader.append(mAttribNames[ct]);
-        mShader.append(";\n");
-    }
-
     for (uint32_t ct=0; ct < mUniformCount; ct++) {
         mShader.append("uniform mat4 ");
         mShader.append(mUniformNames[ct]);
@@ -132,8 +126,34 @@
     mShader.append("varying vec4 varTex0;\n");
 
     if (mUserShader.length() > 1) {
+        for (uint32_t ct=0; ct < mInputCount; ct++) {
+            const Element *e = mInputElements[ct].get();
+            for (uint32_t field=0; field < e->getFieldCount(); field++) {
+                const Element *f = e->getField(field);
+
+                // Cannot be complex
+                rsAssert(!f->getFieldCount());
+                switch(f->getComponent().getVectorSize()) {
+                case 1: mShader.append("attribute float ATTRIB_"); break;
+                case 2: mShader.append("attribute vec2 ATTRIB_"); break;
+                case 3: mShader.append("attribute vec3 ATTRIB_"); break;
+                case 4: mShader.append("attribute vec4 ATTRIB_"); break;
+                default:
+                    rsAssert(0);
+                }
+
+                mShader.append(e->getFieldName(field));
+                mShader.append(";\n");
+            }
+        }
         mShader.append(mUserShader);
     } else {
+        for (uint32_t ct=0; ct < mAttribCount; ct++) {
+            mShader.append("attribute vec4 ");
+            mShader.append(mAttribNames[ct]);
+            mShader.append(";\n");
+        }
+
         mShader.append("void main() {\n");
         mShader.append("  gl_Position = uni_MVP * attrib_Position;\n");
         mShader.append("  gl_PointSize = attrib_PointSize.x;\n");
diff --git a/rsScriptC.cpp b/rsScriptC.cpp
index 9db3127..b7e0b86 100644
--- a/rsScriptC.cpp
+++ b/rsScriptC.cpp
@@ -137,7 +137,6 @@
 
     rsc->appendNameDefines(&tmp);
     appendDecls(&tmp);
-    rsc->appendVarDefines(&tmp);
     appendVarDefines(rsc, &tmp);
     appendTypes(rsc, &tmp);
     tmp.append("#line 1\n");