Piping texture names through shader builder.
Fixing uint size_t mismatch.

Change-Id: Ia7c8bd9f829deaa50e1cc381ccd50f29676bbdfb
diff --git a/graphics/java/android/renderscript/Program.java b/graphics/java/android/renderscript/Program.java
index 3f769ee..4d60ac8 100644
--- a/graphics/java/android/renderscript/Program.java
+++ b/graphics/java/android/renderscript/Program.java
@@ -69,6 +69,7 @@
     Element mOutputs[];
     Type mConstants[];
     TextureType mTextures[];
+    String mTextureNames[];
     int mTextureCount;
     String mShader;
 
@@ -111,6 +112,16 @@
     }
 
     /**
+     * @hide
+     */
+    public String getTextureName(int slot) {
+        if ((slot < 0) || (slot >= mTextureCount)) {
+            throw new IllegalArgumentException("Slot ID out of range.");
+        }
+        return mTextureNames[slot];
+    }
+
+    /**
      * Binds a constant buffer to be used as uniform inputs to the
      * program
      *
@@ -180,6 +191,7 @@
         Type mConstants[];
         Type mTextures[];
         TextureType mTextureTypes[];
+        String mTextureNames[];
         int mInputCount;
         int mOutputCount;
         int mConstantCount;
@@ -197,6 +209,7 @@
             mConstantCount = 0;
             mTextureCount = 0;
             mTextureTypes = new TextureType[MAX_TEXTURE];
+            mTextureNames = new String[MAX_TEXTURE];
         }
 
         /**
@@ -300,10 +313,28 @@
          * @return  self
          */
         public BaseProgramBuilder addTexture(TextureType texType) throws IllegalArgumentException {
+            addTexture(texType, "Tex" + mTextureCount);
+            return this;
+        }
+
+        /**
+         * @hide
+         * Adds a texture input to the Program
+         *
+         * @param texType describes that the texture to append it (2D,
+         *                Cubemap, etc.)
+         * @param texName what the texture should be called in the
+         *                shader
+         * @return  self
+         */
+        public BaseProgramBuilder addTexture(TextureType texType, String texName)
+            throws IllegalArgumentException {
             if(mTextureCount >= MAX_TEXTURE) {
                 throw new IllegalArgumentException("Max texture count exceeded.");
             }
-            mTextureTypes[mTextureCount ++] = texType;
+            mTextureTypes[mTextureCount] = texType;
+            mTextureNames[mTextureCount] = texName;
+            mTextureCount ++;
             return this;
         }
 
@@ -317,6 +348,8 @@
             p.mTextureCount = mTextureCount;
             p.mTextures = new TextureType[mTextureCount];
             System.arraycopy(mTextureTypes, 0, p.mTextures, 0, mTextureCount);
+            p.mTextureNames = new String[mTextureCount];
+            System.arraycopy(mTextureNames, 0, p.mTextureNames, 0, mTextureCount);
         }
     }
 
diff --git a/graphics/java/android/renderscript/ProgramFragment.java b/graphics/java/android/renderscript/ProgramFragment.java
index 21bace8..ebc15e5 100644
--- a/graphics/java/android/renderscript/ProgramFragment.java
+++ b/graphics/java/android/renderscript/ProgramFragment.java
@@ -59,6 +59,7 @@
         public ProgramFragment create() {
             mRS.validate();
             int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
+            String[] texNames = new String[mTextureCount];
             int idx = 0;
 
             for (int i=0; i < mInputCount; i++) {
@@ -76,9 +77,10 @@
             for (int i=0; i < mTextureCount; i++) {
                 tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
                 tmp[idx++] = mTextureTypes[i].mID;
+                texNames[i] = mTextureNames[i];
             }
 
-            int id = mRS.nProgramFragmentCreate(mShader, tmp);
+            int id = mRS.nProgramFragmentCreate(mShader, texNames, tmp);
             ProgramFragment pf = new ProgramFragment(id, mRS);
             initProgram(pf);
             return pf;
diff --git a/graphics/java/android/renderscript/ProgramFragmentFixedFunction.java b/graphics/java/android/renderscript/ProgramFragmentFixedFunction.java
index 0ab73c1..cd31db3 100644
--- a/graphics/java/android/renderscript/ProgramFragmentFixedFunction.java
+++ b/graphics/java/android/renderscript/ProgramFragmentFixedFunction.java
@@ -47,6 +47,7 @@
         public ProgramFragmentFixedFunction create() {
             mRS.validate();
             int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
+            String[] texNames = new String[mTextureCount];
             int idx = 0;
 
             for (int i=0; i < mInputCount; i++) {
@@ -64,9 +65,10 @@
             for (int i=0; i < mTextureCount; i++) {
                 tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
                 tmp[idx++] = mTextureTypes[i].mID;
+                texNames[i] = mTextureNames[i];
             }
 
-            int id = mRS.nProgramFragmentCreate(mShader, tmp);
+            int id = mRS.nProgramFragmentCreate(mShader, texNames, tmp);
             ProgramFragmentFixedFunction pf = new ProgramFragmentFixedFunction(id, mRS);
             initProgram(pf);
             return pf;
diff --git a/graphics/java/android/renderscript/ProgramVertex.java b/graphics/java/android/renderscript/ProgramVertex.java
index b3c1bd9..a6cd15b 100644
--- a/graphics/java/android/renderscript/ProgramVertex.java
+++ b/graphics/java/android/renderscript/ProgramVertex.java
@@ -116,6 +116,7 @@
         public ProgramVertex create() {
             mRS.validate();
             int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
+            String[] texNames = new String[mTextureCount];
             int idx = 0;
 
             for (int i=0; i < mInputCount; i++) {
@@ -133,9 +134,10 @@
             for (int i=0; i < mTextureCount; i++) {
                 tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
                 tmp[idx++] = mTextureTypes[i].mID;
+                texNames[i] = mTextureNames[i];
             }
 
-            int id = mRS.nProgramVertexCreate(mShader, tmp);
+            int id = mRS.nProgramVertexCreate(mShader, texNames, tmp);
             ProgramVertex pv = new ProgramVertex(id, mRS);
             initProgram(pv);
             return pv;
diff --git a/graphics/java/android/renderscript/ProgramVertexFixedFunction.java b/graphics/java/android/renderscript/ProgramVertexFixedFunction.java
index 740d6a5..9a43943 100644
--- a/graphics/java/android/renderscript/ProgramVertexFixedFunction.java
+++ b/graphics/java/android/renderscript/ProgramVertexFixedFunction.java
@@ -70,6 +70,7 @@
         public ProgramVertexFixedFunction create() {
             mRS.validate();
             int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
+            String[] texNames = new String[mTextureCount];
             int idx = 0;
 
             for (int i=0; i < mInputCount; i++) {
@@ -87,9 +88,10 @@
             for (int i=0; i < mTextureCount; i++) {
                 tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
                 tmp[idx++] = mTextureTypes[i].mID;
+                texNames[i] = mTextureNames[i];
             }
 
-            int id = mRS.nProgramVertexCreate(mShader, tmp);
+            int id = mRS.nProgramVertexCreate(mShader, texNames, tmp);
             ProgramVertexFixedFunction pv = new ProgramVertexFixedFunction(id, mRS);
             initProgram(pv);
             return pv;
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index d3c801f2..33b6f74 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -553,15 +553,15 @@
         validate();
         rsnProgramBindSampler(mContext, vpf, slot, s);
     }
-    native int  rsnProgramFragmentCreate(int con, String shader, int[] params);
-    synchronized int nProgramFragmentCreate(String shader, int[] params) {
+    native int  rsnProgramFragmentCreate(int con, String shader, String[] texNames, int[] params);
+    synchronized int nProgramFragmentCreate(String shader, String[] texNames, int[] params) {
         validate();
-        return rsnProgramFragmentCreate(mContext, shader, params);
+        return rsnProgramFragmentCreate(mContext, shader, texNames, params);
     }
-    native int  rsnProgramVertexCreate(int con, String shader, int[] params);
-    synchronized int nProgramVertexCreate(String shader, int[] params) {
+    native int  rsnProgramVertexCreate(int con, String shader, String[] texNames, int[] params);
+    synchronized int nProgramVertexCreate(String shader, String[] texNames, int[] params) {
         validate();
-        return rsnProgramVertexCreate(mContext, shader, params);
+        return rsnProgramVertexCreate(mContext, shader, texNames, params);
     }
 
     native int  rsnMeshCreate(int con, int[] vtx, int[] idx, int[] prim);
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 94f19b3..7986cf9 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -54,13 +54,11 @@
 
 class AutoJavaStringToUTF8 {
 public:
-    AutoJavaStringToUTF8(JNIEnv* env, jstring str) : fEnv(env), fJStr(str)
-    {
+    AutoJavaStringToUTF8(JNIEnv* env, jstring str) : fEnv(env), fJStr(str) {
         fCStr = env->GetStringUTFChars(str, NULL);
         fLength = env->GetStringUTFLength(str);
     }
-    ~AutoJavaStringToUTF8()
-    {
+    ~AutoJavaStringToUTF8() {
         fEnv->ReleaseStringUTFChars(fJStr, fCStr);
     }
     const char* c_str() const { return fCStr; }
@@ -73,6 +71,42 @@
     jsize       fLength;
 };
 
+class AutoJavaStringArrayToUTF8 {
+public:
+    AutoJavaStringArrayToUTF8(JNIEnv* env, jobjectArray strings, jsize stringsLength)
+    : mEnv(env), mStrings(strings), mStringsLength(stringsLength) {
+        mCStrings = NULL;
+        mSizeArray = NULL;
+        if (stringsLength > 0) {
+            mCStrings = (const char **)calloc(stringsLength, sizeof(char *));
+            mSizeArray = (size_t*)calloc(stringsLength, sizeof(size_t));
+            for (jsize ct = 0; ct < stringsLength; ct ++) {
+                jstring s = (jstring)mEnv->GetObjectArrayElement(mStrings, ct);
+                mCStrings[ct] = mEnv->GetStringUTFChars(s, NULL);
+                mSizeArray[ct] = mEnv->GetStringUTFLength(s);
+            }
+        }
+    }
+    ~AutoJavaStringArrayToUTF8() {
+        for (jsize ct=0; ct < mStringsLength; ct++) {
+            jstring s = (jstring)mEnv->GetObjectArrayElement(mStrings, ct);
+            mEnv->ReleaseStringUTFChars(s, mCStrings[ct]);
+        }
+        free(mCStrings);
+        free(mSizeArray);
+    }
+    const char **c_str() const { return mCStrings; }
+    size_t *c_str_len() const { return mSizeArray; }
+    jsize length() const { return mStringsLength; }
+
+private:
+    JNIEnv      *mEnv;
+    jobjectArray mStrings;
+    const char **mCStrings;
+    size_t      *mSizeArray;
+    jsize        mStringsLength;
+};
+
 // ---------------------------------------------------------------------------
 
 static jfieldID gContextId = 0;
@@ -322,33 +356,27 @@
 }
 
 static jint
-nElementCreate2(JNIEnv *_env, jobject _this, RsContext con, jintArray _ids, jobjectArray _names, jintArray _arraySizes)
+nElementCreate2(JNIEnv *_env, jobject _this, RsContext con,
+                jintArray _ids, jobjectArray _names, jintArray _arraySizes)
 {
     int fieldCount = _env->GetArrayLength(_ids);
     LOG_API("nElementCreate2, con(%p)", con);
 
     jint *ids = _env->GetIntArrayElements(_ids, NULL);
     jint *arraySizes = _env->GetIntArrayElements(_arraySizes, NULL);
-    const char ** nameArray = (const char **)calloc(fieldCount, sizeof(char *));
-    size_t* sizeArray = (size_t*)calloc(fieldCount, sizeof(size_t));
 
-    for (int ct=0; ct < fieldCount; ct++) {
-        jstring s = (jstring)_env->GetObjectArrayElement(_names, ct);
-        nameArray[ct] = _env->GetStringUTFChars(s, NULL);
-        sizeArray[ct] = _env->GetStringUTFLength(s);
-    }
+    AutoJavaStringArrayToUTF8 names(_env, _names, fieldCount);
+
+    const char **nameArray = names.c_str();
+    size_t *sizeArray = names.c_str_len();
+
     jint id = (jint)rsElementCreate2(con,
                                      (RsElement *)ids, fieldCount,
                                      nameArray, fieldCount * sizeof(size_t),  sizeArray,
                                      (const uint32_t *)arraySizes, fieldCount);
-    for (int ct=0; ct < fieldCount; ct++) {
-        jstring s = (jstring)_env->GetObjectArrayElement(_names, ct);
-        _env->ReleaseStringUTFChars(s, nameArray[ct]);
-    }
+
     _env->ReleaseIntArrayElements(_ids, ids, JNI_ABORT);
     _env->ReleaseIntArrayElements(_arraySizes, arraySizes, JNI_ABORT);
-    free(nameArray);
-    free(sizeArray);
     return (jint)id;
 }
 
@@ -1033,15 +1061,24 @@
 // ---------------------------------------------------------------------------
 
 static jint
-nProgramFragmentCreate(JNIEnv *_env, jobject _this, RsContext con, jstring shader, jintArray params)
+nProgramFragmentCreate(JNIEnv *_env, jobject _this, RsContext con, jstring shader,
+                       jobjectArray texNames, jintArray params)
 {
     AutoJavaStringToUTF8 shaderUTF(_env, shader);
     jint *paramPtr = _env->GetIntArrayElements(params, NULL);
     jint paramLen = _env->GetArrayLength(params);
 
+    int texCount = _env->GetArrayLength(texNames);
+    AutoJavaStringArrayToUTF8 names(_env, texNames, texCount);
+    const char ** nameArray = names.c_str();
+    size_t* sizeArray = names.c_str_len();
+
     LOG_API("nProgramFragmentCreate, con(%p), paramLen(%i)", con, paramLen);
 
-    jint ret = (jint)rsProgramFragmentCreate(con, shaderUTF.c_str(), shaderUTF.length(), (uint32_t *)paramPtr, paramLen);
+    jint ret = (jint)rsProgramFragmentCreate(con, shaderUTF.c_str(), shaderUTF.length(),
+                                             nameArray, texCount, sizeArray,
+                                             (uint32_t *)paramPtr, paramLen);
+
     _env->ReleaseIntArrayElements(params, paramPtr, JNI_ABORT);
     return ret;
 }
@@ -1050,7 +1087,8 @@
 // ---------------------------------------------------------------------------
 
 static jint
-nProgramVertexCreate(JNIEnv *_env, jobject _this, RsContext con, jstring shader, jintArray params)
+nProgramVertexCreate(JNIEnv *_env, jobject _this, RsContext con, jstring shader,
+                     jobjectArray texNames, jintArray params)
 {
     AutoJavaStringToUTF8 shaderUTF(_env, shader);
     jint *paramPtr = _env->GetIntArrayElements(params, NULL);
@@ -1058,7 +1096,15 @@
 
     LOG_API("nProgramVertexCreate, con(%p), paramLen(%i)", con, paramLen);
 
-    jint ret = (jint)rsProgramVertexCreate(con, shaderUTF.c_str(), shaderUTF.length(), (uint32_t *)paramPtr, paramLen);
+    int texCount = _env->GetArrayLength(texNames);
+    AutoJavaStringArrayToUTF8 names(_env, texNames, texCount);
+    const char ** nameArray = names.c_str();
+    size_t* sizeArray = names.c_str_len();
+
+    jint ret = (jint)rsProgramVertexCreate(con, shaderUTF.c_str(), shaderUTF.length(),
+                                           nameArray, texCount, sizeArray,
+                                           (uint32_t *)paramPtr, paramLen);
+
     _env->ReleaseIntArrayElements(params, paramPtr, JNI_ABORT);
     return ret;
 }
@@ -1317,9 +1363,9 @@
 {"rsnProgramBindTexture",            "(IIII)V",                               (void*)nProgramBindTexture },
 {"rsnProgramBindSampler",            "(IIII)V",                               (void*)nProgramBindSampler },
 
-{"rsnProgramFragmentCreate",         "(ILjava/lang/String;[I)I",              (void*)nProgramFragmentCreate },
+{"rsnProgramFragmentCreate",         "(ILjava/lang/String;[Ljava/lang/String;[I)I",              (void*)nProgramFragmentCreate },
 {"rsnProgramRasterCreate",           "(IZI)I",                                (void*)nProgramRasterCreate },
-{"rsnProgramVertexCreate",           "(ILjava/lang/String;[I)I",              (void*)nProgramVertexCreate },
+{"rsnProgramVertexCreate",           "(ILjava/lang/String;[Ljava/lang/String;[I)I",              (void*)nProgramVertexCreate },
 
 {"rsnContextBindRootScript",         "(II)V",                                 (void*)nContextBindRootScript },
 {"rsnContextBindProgramStore",       "(II)V",                                 (void*)nContextBindProgramStore },
diff --git a/libs/rs/driver/rsdProgram.cpp b/libs/rs/driver/rsdProgram.cpp
index 852b6bf..fa4cb0f 100644
--- a/libs/rs/driver/rsdProgram.cpp
+++ b/libs/rs/driver/rsdProgram.cpp
@@ -34,8 +34,11 @@
 using namespace android::renderscript;
 
 bool rsdProgramVertexInit(const Context *rsc, const ProgramVertex *pv,
-                          const char* shader, size_t shaderLen) {
-    RsdShader *drv = new RsdShader(pv, GL_VERTEX_SHADER, shader, shaderLen);
+                          const char* shader, size_t shaderLen,
+                          const char** textureNames, size_t textureNamesCount,
+                          const size_t *textureNamesLength) {
+    RsdShader *drv = new RsdShader(pv, GL_VERTEX_SHADER, shader, shaderLen,
+                                   textureNames, textureNamesCount, textureNamesLength);
     pv->mHal.drv = drv;
 
     return drv->createShader();
@@ -78,8 +81,11 @@
 }
 
 bool rsdProgramFragmentInit(const Context *rsc, const ProgramFragment *pf,
-                          const char* shader, size_t shaderLen) {
-    RsdShader *drv = new RsdShader(pf, GL_FRAGMENT_SHADER, shader, shaderLen);
+                            const char* shader, size_t shaderLen,
+                            const char** textureNames, size_t textureNamesCount,
+                            const size_t *textureNamesLength) {
+    RsdShader *drv = new RsdShader(pf, GL_FRAGMENT_SHADER, shader, shaderLen,
+                                   textureNames, textureNamesCount, textureNamesLength);
     pf->mHal.drv = drv;
 
     return drv->createShader();
diff --git a/libs/rs/driver/rsdProgramFragment.h b/libs/rs/driver/rsdProgramFragment.h
index 366cb40..b03a9fe 100644
--- a/libs/rs/driver/rsdProgramFragment.h
+++ b/libs/rs/driver/rsdProgramFragment.h
@@ -22,7 +22,9 @@
 
 bool rsdProgramFragmentInit(const android::renderscript::Context *rsc,
                             const android::renderscript::ProgramFragment *,
-                            const char* shader, uint32_t shaderLen);
+                            const char* shader, size_t shaderLen,
+                            const char** textureNames, size_t textureNamesCount,
+                            const size_t *textureNamesLength);
 void rsdProgramFragmentSetActive(const android::renderscript::Context *rsc,
                                  const android::renderscript::ProgramFragment *);
 void rsdProgramFragmentDestroy(const android::renderscript::Context *rsc,
diff --git a/libs/rs/driver/rsdProgramVertex.h b/libs/rs/driver/rsdProgramVertex.h
index e998572..f917a41 100644
--- a/libs/rs/driver/rsdProgramVertex.h
+++ b/libs/rs/driver/rsdProgramVertex.h
@@ -21,7 +21,9 @@
 
 bool rsdProgramVertexInit(const android::renderscript::Context *rsc,
                           const android::renderscript::ProgramVertex *,
-                          const char* shader, uint32_t shaderLen);
+                          const char* shader, size_t shaderLen,
+                          const char** textureNames, size_t textureNamesCount,
+                          const size_t *textureNamesLength);
 void rsdProgramVertexSetActive(const android::renderscript::Context *rsc,
                                const android::renderscript::ProgramVertex *);
 void rsdProgramVertexDestroy(const android::renderscript::Context *rsc,
diff --git a/libs/rs/driver/rsdShader.cpp b/libs/rs/driver/rsdShader.cpp
index 0e5b388..1e73b95 100644
--- a/libs/rs/driver/rsdShader.cpp
+++ b/libs/rs/driver/rsdShader.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2011-2012 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.
@@ -30,14 +30,16 @@
 using namespace android::renderscript;
 
 RsdShader::RsdShader(const Program *p, uint32_t type,
-                       const char * shaderText, size_t shaderLength) {
-
+                     const char * shaderText, size_t shaderLength,
+                     const char** textureNames, size_t textureNamesCount,
+                     const size_t *textureNamesLength) {
     mUserShader.setTo(shaderText, shaderLength);
     mRSProgram = p;
     mType = type;
     initMemberVars();
     initAttribAndUniformArray();
-    init();
+    init(textureNames, textureNamesCount, textureNamesLength);
+    createTexturesString(textureNames, textureNamesCount, textureNamesLength);
 }
 
 RsdShader::~RsdShader() {
@@ -65,25 +67,26 @@
     mIsValid = false;
 }
 
-void RsdShader::init() {
+void RsdShader::init(const char** textureNames, size_t textureNamesCount,
+                     const size_t *textureNamesLength) {
     uint32_t attribCount = 0;
     uint32_t uniformCount = 0;
     for (uint32_t ct=0; ct < mRSProgram->mHal.state.inputElementsCount; ct++) {
-        initAddUserElement(mRSProgram->mHal.state.inputElements[ct], mAttribNames, NULL, &attribCount, RS_SHADER_ATTR);
+        initAddUserElement(mRSProgram->mHal.state.inputElements[ct], mAttribNames,
+                           NULL, &attribCount, RS_SHADER_ATTR);
     }
     for (uint32_t ct=0; ct < mRSProgram->mHal.state.constantsCount; ct++) {
-        initAddUserElement(mRSProgram->mHal.state.constantTypes[ct]->getElement(), mUniformNames, mUniformArraySizes, &uniformCount, RS_SHADER_UNI);
+        initAddUserElement(mRSProgram->mHal.state.constantTypes[ct]->getElement(),
+                           mUniformNames, mUniformArraySizes, &uniformCount, RS_SHADER_UNI);
     }
 
     mTextureUniformIndexStart = uniformCount;
-    char buf[256];
     for (uint32_t ct=0; ct < mRSProgram->mHal.state.texturesCount; ct++) {
-        snprintf(buf, sizeof(buf), "UNI_Tex%i", ct);
-        mUniformNames[uniformCount].setTo(buf);
+        mUniformNames[uniformCount].setTo("UNI_");
+        mUniformNames[uniformCount].append(textureNames[ct], textureNamesLength[ct]);
         mUniformArraySizes[uniformCount] = 1;
         uniformCount++;
     }
-
 }
 
 String8 RsdShader::getGLSLInputString() const {
@@ -135,22 +138,25 @@
     }
 }
 
-void RsdShader::appendTextures() {
-    char buf[256];
-    for (uint32_t ct=0; ct < mRSProgram->mHal.state.texturesCount; ct++) {
+void RsdShader::createTexturesString(const char** textureNames, size_t textureNamesCount,
+                                     const size_t *textureNamesLength) {
+    mShaderTextures.setTo("");
+    for (uint32_t ct = 0; ct < mRSProgram->mHal.state.texturesCount; ct ++) {
         if (mRSProgram->mHal.state.textureTargets[ct] == RS_TEXTURE_2D) {
             Allocation *a = mRSProgram->mHal.state.textures[ct];
             if (a && a->mHal.state.surfaceTextureID) {
-                snprintf(buf, sizeof(buf), "uniform samplerExternalOES UNI_Tex%i;\n", ct);
+                mShaderTextures.append("uniform samplerExternalOES UNI_");
             } else {
-                snprintf(buf, sizeof(buf), "uniform sampler2D UNI_Tex%i;\n", ct);
+                mShaderTextures.append("uniform sampler2D UNI_");
             }
             mTextureTargets[ct] = GL_TEXTURE_2D;
         } else {
-            snprintf(buf, sizeof(buf), "uniform samplerCube UNI_Tex%i;\n", ct);
+            mShaderTextures.append("uniform samplerCube UNI_");
             mTextureTargets[ct] = GL_TEXTURE_CUBE_MAP;
         }
-        mShader.append(buf);
+
+        mShaderTextures.append(textureNames[ct], textureNamesLength[ct]);
+        mShaderTextures.append(";\n");
     }
 }
 
@@ -161,7 +167,7 @@
     }
     appendUserConstants();
     appendAttributes();
-    appendTextures();
+    mShader.append(mShaderTextures);
 
     mShader.append(mUserShader);
 
@@ -418,7 +424,8 @@
 
         DrvAllocation *drvTex = (DrvAllocation *)mRSProgram->mHal.state.textures[ct]->mHal.drv;
         if (drvTex->glTarget != GL_TEXTURE_2D && drvTex->glTarget != GL_TEXTURE_CUBE_MAP) {
-            ALOGE("Attempting to bind unknown texture to shader id %u, texture unit %u", (uint)this, ct);
+            ALOGE("Attempting to bind unknown texture to shader id %u, texture unit %u",
+                  (uint)this, ct);
             rsc->setError(RS_ERROR_BAD_SHADER, "Non-texture allocation bound to a shader");
         }
         RSD_CALL_GL(glBindTexture, drvTex->glTarget, drvTex->textureID);
diff --git a/libs/rs/driver/rsdShader.h b/libs/rs/driver/rsdShader.h
index 3f0d6ea..e32145f 100644
--- a/libs/rs/driver/rsdShader.h
+++ b/libs/rs/driver/rsdShader.h
@@ -39,7 +39,9 @@
 public:
 
     RsdShader(const android::renderscript::Program *p, uint32_t type,
-               const char * shaderText, uint32_t shaderLength);
+              const char * shaderText, uint32_t shaderLength,
+              const char** textureNames, size_t textureNamesCount,
+              const size_t *textureNamesLength);
     virtual ~RsdShader();
 
     bool createShader();
@@ -67,19 +69,27 @@
 
     // Applies to vertex and fragment shaders only
     void appendUserConstants();
-    void setupUserConstants(const android::renderscript::Context *rsc, RsdShaderCache *sc, bool isFragment);
-    void initAddUserElement(const android::renderscript::Element *e, android::String8 *names, uint32_t *arrayLengths, uint32_t *count, const char *prefix);
+    void setupUserConstants(const android::renderscript::Context *rsc,
+                            RsdShaderCache *sc, bool isFragment);
+    void initAddUserElement(const android::renderscript::Element *e,
+                            android::String8 *names, uint32_t *arrayLengths,
+                            uint32_t *count, const char *prefix);
     void setupTextures(const android::renderscript::Context *rsc, RsdShaderCache *sc);
-    void setupSampler(const android::renderscript::Context *rsc, const android::renderscript::Sampler *s, const android::renderscript::Allocation *tex);
+    void setupSampler(const android::renderscript::Context *rsc,
+                      const android::renderscript::Sampler *s,
+                      const android::renderscript::Allocation *tex);
 
     void appendAttributes();
     void appendTextures();
+    void createTexturesString(const char** textureNames, size_t textureNamesCount,
+                              const size_t *textureNamesLength);
 
     void initAttribAndUniformArray();
 
     mutable bool mDirty;
     android::String8 mShader;
     android::String8 mUserShader;
+    android::String8 mShaderTextures;
     uint32_t mShaderID;
     uint32_t mType;
 
@@ -93,10 +103,14 @@
 
     int32_t mTextureUniformIndexStart;
 
-    void logUniform(const android::renderscript::Element *field, const float *fd, uint32_t arraySize );
-    void setUniform(const android::renderscript::Context *rsc, const android::renderscript::Element *field, const float *fd, int32_t slot, uint32_t arraySize );
+    void logUniform(const android::renderscript::Element *field,
+                    const float *fd, uint32_t arraySize);
+    void setUniform(const android::renderscript::Context *rsc,
+                    const android::renderscript::Element *field,
+                    const float *fd, int32_t slot, uint32_t arraySize );
     void initMemberVars();
-    void init();
+    void init(const char** textureNames, size_t textureNamesCount,
+              const size_t *textureNamesLength);
 };
 
 #endif //ANDROID_RSD_SHADER_H
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 6759bc7..dc846aa 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -70,167 +70,167 @@
 }
 
 ContextFinish {
-	sync
-	}
+    sync
+    }
 
 ContextBindRootScript {
-	param RsScript sampler
-	}
+    param RsScript sampler
+    }
 
 ContextBindProgramStore {
-	param RsProgramStore pgm
-	}
+    param RsProgramStore pgm
+    }
 
 ContextBindProgramFragment {
-	param RsProgramFragment pgm
-	}
+    param RsProgramFragment pgm
+    }
 
 ContextBindProgramVertex {
-	param RsProgramVertex pgm
-	}
+    param RsProgramVertex pgm
+    }
 
 ContextBindProgramRaster {
-	param RsProgramRaster pgm
-	}
+    param RsProgramRaster pgm
+    }
 
 ContextBindFont {
-	param RsFont pgm
-	}
+    param RsFont pgm
+    }
 
 ContextPause {
-	}
+    }
 
 ContextResume {
-	}
+    }
 
 ContextSetSurface {
-	param uint32_t width
-	param uint32_t height
-	param RsNativeWindow sur
+    param uint32_t width
+    param uint32_t height
+    param RsNativeWindow sur
         sync
-	}
+    }
 
 ContextDump {
-	param int32_t bits
+    param int32_t bits
 }
 
 ContextSetPriority {
-	param int32_t priority
-	}
+    param int32_t priority
+    }
 
 ContextDestroyWorker {
         sync
 }
 
 AssignName {
-	param RsObjectBase obj
-	param const char *name
-	}
+    param RsObjectBase obj
+    param const char *name
+    }
 
 ObjDestroy {
-	param RsAsyncVoidPtr objPtr
-	}
+    param RsAsyncVoidPtr objPtr
+    }
 
 ElementCreate {
         direct
-	param RsDataType mType
-	param RsDataKind mKind
-	param bool mNormalized
-	param uint32_t mVectorSize
-	ret RsElement
-	}
+    param RsDataType mType
+    param RsDataKind mKind
+    param bool mNormalized
+    param uint32_t mVectorSize
+    ret RsElement
+    }
 
 ElementCreate2 {
         direct
-	param const RsElement * elements
-	param const char ** names
-	param const uint32_t * arraySize
-	ret RsElement
-	}
+    param const RsElement * elements
+    param const char ** names
+    param const uint32_t * arraySize
+    ret RsElement
+    }
 
 AllocationCopyToBitmap {
-	param RsAllocation alloc
-	param void * data
-	}
+    param RsAllocation alloc
+    param void * data
+    }
 
 
 Allocation1DData {
-	param RsAllocation va
-	param uint32_t xoff
-	param uint32_t lod
-	param uint32_t count
-	param const void *data
-	}
+    param RsAllocation va
+    param uint32_t xoff
+    param uint32_t lod
+    param uint32_t count
+    param const void *data
+    }
 
 Allocation1DElementData {
-	param RsAllocation va
-	param uint32_t x
-	param uint32_t lod
-	param const void *data
-	param size_t comp_offset
-	}
+    param RsAllocation va
+    param uint32_t x
+    param uint32_t lod
+    param const void *data
+    param size_t comp_offset
+    }
 
 Allocation2DData {
-	param RsAllocation va
-	param uint32_t xoff
-	param uint32_t yoff
-	param uint32_t lod
-	param RsAllocationCubemapFace face
-	param uint32_t w
-	param uint32_t h
-	param const void *data
-	}
+    param RsAllocation va
+    param uint32_t xoff
+    param uint32_t yoff
+    param uint32_t lod
+    param RsAllocationCubemapFace face
+    param uint32_t w
+    param uint32_t h
+    param const void *data
+    }
 
 Allocation2DElementData {
-	param RsAllocation va
-	param uint32_t x
-	param uint32_t y
-	param uint32_t lod
-	param RsAllocationCubemapFace face
-	param const void *data
-	param size_t element_offset
-	}
+    param RsAllocation va
+    param uint32_t x
+    param uint32_t y
+    param uint32_t lod
+    param RsAllocationCubemapFace face
+    param const void *data
+    param size_t element_offset
+    }
 
 AllocationGenerateMipmaps {
-	param RsAllocation va
+    param RsAllocation va
 }
 
 AllocationRead {
-	param RsAllocation va
-	param void * data
-	}
+    param RsAllocation va
+    param void * data
+    }
 
 AllocationSyncAll {
-	param RsAllocation va
-	param RsAllocationUsageType src
+    param RsAllocation va
+    param RsAllocationUsageType src
 }
 
 
 AllocationResize1D {
-	param RsAllocation va
-	param uint32_t dimX
-	}
+    param RsAllocation va
+    param uint32_t dimX
+    }
 
 AllocationResize2D {
-	param RsAllocation va
-	param uint32_t dimX
-	param uint32_t dimY
-	}
+    param RsAllocation va
+    param uint32_t dimX
+    param uint32_t dimY
+    }
 
 AllocationCopy2DRange {
-	param RsAllocation dest
-	param uint32_t destXoff
-	param uint32_t destYoff
-	param uint32_t destMip
-	param uint32_t destFace
-	param uint32_t width
-	param uint32_t height
-	param RsAllocation src
-	param uint32_t srcXoff
-	param uint32_t srcYoff
-	param uint32_t srcMip
-	param uint32_t srcFace
-	}
+    param RsAllocation dest
+    param uint32_t destXoff
+    param uint32_t destYoff
+    param uint32_t destMip
+    param uint32_t destFace
+    param uint32_t width
+    param uint32_t height
+    param RsAllocation src
+    param uint32_t srcXoff
+    param uint32_t srcYoff
+    param uint32_t srcMip
+    param uint32_t srcFace
+    }
 
 SamplerCreate {
     direct
@@ -244,26 +244,26 @@
 }
 
 ScriptBindAllocation {
-	param RsScript vtm
-	param RsAllocation va
-	param uint32_t slot
-	}
+    param RsScript vtm
+    param RsAllocation va
+    param uint32_t slot
+    }
 
 ScriptSetTimeZone {
-	param RsScript s
-	param const char * timeZone
-	}
+    param RsScript s
+    param const char * timeZone
+    }
 
 ScriptInvoke {
-	param RsScript s
-	param uint32_t slot
-	}
+    param RsScript s
+    param uint32_t slot
+    }
 
 ScriptInvokeV {
-	param RsScript s
-	param uint32_t slot
-	param const void * data
-	}
+    param RsScript s
+    param uint32_t slot
+    param const void * data
+    }
 
 ScriptForEach {
     param RsScript s
@@ -274,125 +274,127 @@
 }
 
 ScriptSetVarI {
-	param RsScript s
-	param uint32_t slot
-	param int value
-	}
+    param RsScript s
+    param uint32_t slot
+    param int value
+    }
 
 ScriptSetVarObj {
-	param RsScript s
-	param uint32_t slot
-	param RsObjectBase value
-	}
+    param RsScript s
+    param uint32_t slot
+    param RsObjectBase value
+    }
 
 ScriptSetVarJ {
-	param RsScript s
-	param uint32_t slot
-	param int64_t value
-	}
+    param RsScript s
+    param uint32_t slot
+    param int64_t value
+    }
 
 ScriptSetVarF {
-	param RsScript s
-	param uint32_t slot
-	param float value
-	}
+    param RsScript s
+    param uint32_t slot
+    param float value
+    }
 
 ScriptSetVarD {
-	param RsScript s
-	param uint32_t slot
-	param double value
-	}
+    param RsScript s
+    param uint32_t slot
+    param double value
+    }
 
 ScriptSetVarV {
-	param RsScript s
-	param uint32_t slot
-	param const void * data
-	}
+    param RsScript s
+    param uint32_t slot
+    param const void * data
+    }
 
 
 ScriptCCreate {
         param const char * resName
         param const char * cacheDir
-	param const char * text
-	ret RsScript
-	}
+    param const char * text
+    ret RsScript
+    }
 
 
 ProgramStoreCreate {
-	direct
-	param bool colorMaskR
-	param bool colorMaskG
-	param bool colorMaskB
-	param bool colorMaskA
+    direct
+    param bool colorMaskR
+    param bool colorMaskG
+    param bool colorMaskB
+    param bool colorMaskA
         param bool depthMask
         param bool ditherEnable
-	param RsBlendSrcFunc srcFunc
-	param RsBlendDstFunc destFunc
+    param RsBlendSrcFunc srcFunc
+    param RsBlendDstFunc destFunc
         param RsDepthFunc depthFunc
-	ret RsProgramStore
-	}
+    ret RsProgramStore
+    }
 
 ProgramRasterCreate {
-	direct
-	param bool pointSprite
-	param RsCullMode cull
-	ret RsProgramRaster
+    direct
+    param bool pointSprite
+    param RsCullMode cull
+    ret RsProgramRaster
 }
 
 ProgramBindConstants {
-	param RsProgram vp
-	param uint32_t slot
-	param RsAllocation constants
-	}
+    param RsProgram vp
+    param uint32_t slot
+    param RsAllocation constants
+    }
 
 
 ProgramBindTexture {
-	param RsProgramFragment pf
-	param uint32_t slot
-	param RsAllocation a
-	}
+    param RsProgramFragment pf
+    param uint32_t slot
+    param RsAllocation a
+    }
 
 ProgramBindSampler {
-	param RsProgramFragment pf
-	param uint32_t slot
-	param RsSampler s
-	}
+    param RsProgramFragment pf
+    param uint32_t slot
+    param RsSampler s
+    }
 
 ProgramFragmentCreate {
-	direct
-	param const char * shaderText
-	param const uint32_t * params
-	ret RsProgramFragment
-	}
+    direct
+    param const char * shaderText
+    param const char ** textureNames
+    param const uint32_t * params
+    ret RsProgramFragment
+    }
 
 ProgramVertexCreate {
-	direct
-	param const char * shaderText
-	param const uint32_t * params
-	ret RsProgramVertex
-	}
+    direct
+    param const char * shaderText
+    param const char ** textureNames
+    param const uint32_t * params
+    ret RsProgramVertex
+    }
 
 FontCreateFromFile {
-	param const char *name
-	param float fontSize
-	param uint32_t dpi
-	ret RsFont
-	}
+    param const char *name
+    param float fontSize
+    param uint32_t dpi
+    ret RsFont
+    }
 
 FontCreateFromMemory {
-	param const char *name
-	param float fontSize
-	param uint32_t dpi
-	param const void *data
-	ret RsFont
-	}
+    param const char *name
+    param float fontSize
+    param uint32_t dpi
+    param const void *data
+    ret RsFont
+    }
 
 MeshCreate {
-	param RsAllocation *vtx
-	param RsAllocation *idx
-	param uint32_t *primType
-	ret RsMesh
-	}
+    param RsAllocation *vtx
+    param RsAllocation *idx
+    param uint32_t *primType
+    ret RsMesh
+    }
 
 PathCreate {
     param RsPathPrimitive pp
@@ -402,4 +404,3 @@
     param float quality
     ret RsPath
     }
-
diff --git a/libs/rs/rsFont.cpp b/libs/rs/rsFont.cpp
index 4f21b3b..c4276cf 100644
--- a/libs/rs/rsFont.cpp
+++ b/libs/rs/rsFont.cpp
@@ -490,8 +490,14 @@
     shaderString.append("  gl_FragColor = col;\n");
     shaderString.append("}\n");
 
-    ObjectBaseRef<const Element> colorElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4);
-    ObjectBaseRef<const Element> gammaElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1);
+    const char *textureNames[] = { "Tex0" };
+    const size_t textureNamesLengths[] = { 4 };
+    size_t numTextures = sizeof(textureNamesLengths)/sizeof(*textureNamesLengths);
+
+    ObjectBaseRef<const Element> colorElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32,
+                                                                RS_KIND_USER, false, 4);
+    ObjectBaseRef<const Element> gammaElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32,
+                                                                RS_KIND_USER, false, 1);
     Element::Builder builder;
     builder.add(colorElem.get(), "Color", 1);
     builder.add(gammaElem.get(), "Gamma", 1);
@@ -506,14 +512,17 @@
     tmp[3] = RS_TEXTURE_2D;
 
     mFontShaderFConstant.set(Allocation::createAllocation(mRSC, inputType.get(),
-                                            RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS));
-    ProgramFragment *pf = new ProgramFragment(mRSC, shaderString.string(),
-                                              shaderString.length(), tmp, 4);
+                                                          RS_ALLOCATION_USAGE_SCRIPT |
+                                                          RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS));
+    ProgramFragment *pf = new ProgramFragment(mRSC, shaderString.string(), shaderString.length(),
+                                              textureNames, numTextures, textureNamesLengths,
+                                              tmp, 4);
     mFontShaderF.set(pf);
     mFontShaderF->bindAllocation(mRSC, mFontShaderFConstant.get(), 0);
 
     mFontSampler.set(Sampler::getSampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST,
-                                         RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP).get());
+                                         RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP,
+                                         RS_SAMPLER_CLAMP).get());
     mFontShaderF->bindSampler(mRSC, 0, mFontSampler.get());
 
     mFontProgramStore.set(ProgramStore::getProgramStore(mRSC, true, true, true, true,
@@ -525,10 +534,12 @@
 }
 
 void FontState::initTextTexture() {
-    ObjectBaseRef<const Element> alphaElem = Element::createRef(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1);
+    ObjectBaseRef<const Element> alphaElem = Element::createRef(mRSC, RS_TYPE_UNSIGNED_8,
+                                                                RS_KIND_PIXEL_A, true, 1);
 
     // We will allocate a texture to initially hold 32 character bitmaps
-    ObjectBaseRef<Type> texType = Type::getTypeRef(mRSC, alphaElem.get(), 1024, 256, 0, false, false);
+    ObjectBaseRef<Type> texType = Type::getTypeRef(mRSC, alphaElem.get(),
+                                                   1024, 256, 0, false, false);
 
     Allocation *cacheAlloc = Allocation::createAllocation(mRSC, texType.get(),
                                 RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE);
diff --git a/libs/rs/rsProgram.cpp b/libs/rs/rsProgram.cpp
index 8061515..7114f29 100644
--- a/libs/rs/rsProgram.cpp
+++ b/libs/rs/rsProgram.cpp
@@ -20,8 +20,8 @@
 using namespace android;
 using namespace android::renderscript;
 
-Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength,
-                 const uint32_t * params, uint32_t paramLength)
+Program::Program(Context *rsc, const char * shaderText, size_t shaderLength,
+                 const uint32_t * params, size_t paramLength)
     : ProgramBase(rsc) {
 
     initMemberVars();
diff --git a/libs/rs/rsProgram.h b/libs/rs/rsProgram.h
index 06fc3ec..d032930 100644
--- a/libs/rs/rsProgram.h
+++ b/libs/rs/rsProgram.h
@@ -58,8 +58,8 @@
     };
     Hal mHal;
 
-    Program(Context *, const char * shaderText, uint32_t shaderLength,
-                       const uint32_t * params, uint32_t paramLength);
+    Program(Context *, const char * shaderText, size_t shaderLength,
+            const uint32_t * params, size_t paramLength);
     virtual ~Program();
     virtual bool freeChildren();
 
diff --git a/libs/rs/rsProgramFragment.cpp b/libs/rs/rsProgramFragment.cpp
index 4e73ca6..bebde1e 100644
--- a/libs/rs/rsProgramFragment.cpp
+++ b/libs/rs/rsProgramFragment.cpp
@@ -20,16 +20,18 @@
 using namespace android;
 using namespace android::renderscript;
 
-ProgramFragment::ProgramFragment(Context *rsc, const char * shaderText,
-                                 uint32_t shaderLength, const uint32_t * params,
-                                 uint32_t paramLength)
+ProgramFragment::ProgramFragment(Context *rsc, const char * shaderText, size_t shaderLength,
+                                 const char** textureNames, size_t textureNamesCount, const size_t *textureNamesLength,
+
+                                 const uint32_t * params, size_t paramLength)
     : Program(rsc, shaderText, shaderLength, params, paramLength) {
     mConstantColor[0] = 1.f;
     mConstantColor[1] = 1.f;
     mConstantColor[2] = 1.f;
     mConstantColor[3] = 1.f;
 
-    mRSC->mHal.funcs.fragment.init(mRSC, this, mUserShader.string(), mUserShader.length());
+    mRSC->mHal.funcs.fragment.init(mRSC, this, mUserShader.string(), mUserShader.length(),
+                                   textureNames, textureNamesCount, textureNamesLength);
 }
 
 ProgramFragment::~ProgramFragment() {
@@ -110,8 +112,8 @@
 
     Allocation *constAlloc = Allocation::createAllocation(rsc, inputType.get(),
                               RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS);
-    ProgramFragment *pf = new ProgramFragment(rsc, shaderString.string(),
-                                              shaderString.length(), tmp, 2);
+    ProgramFragment *pf = new ProgramFragment(rsc, shaderString.string(), shaderString.length(),
+                                              NULL, 0, NULL, tmp, 2);
     pf->bindAllocation(rsc, constAlloc, 0);
     pf->setConstantColor(rsc, 1.0f, 1.0f, 1.0f, 1.0f);
 
@@ -127,9 +129,14 @@
 namespace renderscript {
 
 RsProgramFragment rsi_ProgramFragmentCreate(Context *rsc, const char * shaderText,
-                             size_t shaderLength, const uint32_t * params,
-                             size_t paramLength) {
-    ProgramFragment *pf = new ProgramFragment(rsc, shaderText, shaderLength, params, paramLength);
+                                            size_t shaderLength,
+                                            const char** textureNames,
+                                            size_t textureNamesCount,
+                                            const size_t *textureNamesLength,
+                                            const uint32_t * params, size_t paramLength) {
+    ProgramFragment *pf = new ProgramFragment(rsc, shaderText, shaderLength,
+                                              textureNames, textureNamesCount, textureNamesLength,
+                                              params, paramLength);
     pf->incUserRef();
     //ALOGE("rsi_ProgramFragmentCreate %p", pf);
     return pf;
diff --git a/libs/rs/rsProgramFragment.h b/libs/rs/rsProgramFragment.h
index d6e20cd..4eb28e7 100644
--- a/libs/rs/rsProgramFragment.h
+++ b/libs/rs/rsProgramFragment.h
@@ -27,9 +27,9 @@
 
 class ProgramFragment : public Program {
 public:
-    ProgramFragment(Context *rsc, const char * shaderText,
-                             uint32_t shaderLength, const uint32_t * params,
-                             uint32_t paramLength);
+    ProgramFragment(Context *rsc, const char * shaderText, size_t shaderLength,
+                    const char** textureNames, size_t textureNamesCount, const size_t *textureNamesLength,
+                     const uint32_t * params, size_t paramLength);
     virtual ~ProgramFragment();
 
     virtual void setup(Context *, ProgramFragmentState *);
diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp
index 871caac..c8a53ea 100644
--- a/libs/rs/rsProgramVertex.cpp
+++ b/libs/rs/rsProgramVertex.cpp
@@ -21,11 +21,13 @@
 using namespace android::renderscript;
 
 
-ProgramVertex::ProgramVertex(Context *rsc, const char * shaderText,
-                             uint32_t shaderLength, const uint32_t * params,
-                             uint32_t paramLength)
+ProgramVertex::ProgramVertex(Context *rsc, const char * shaderText, size_t shaderLength,
+                             const char** textureNames, size_t textureNamesCount, const size_t *textureNamesLength,
+
+                             const uint32_t * params, size_t paramLength)
     : Program(rsc, shaderText, shaderLength, params, paramLength) {
-    mRSC->mHal.funcs.vertex.init(mRSC, this, mUserShader.string(), mUserShader.length());
+    mRSC->mHal.funcs.vertex.init(mRSC, this, mUserShader.string(), mUserShader.length(),
+                                 textureNames, textureNamesCount, textureNamesLength);
 }
 
 ProgramVertex::~ProgramVertex() {
@@ -191,8 +193,8 @@
     tmp[2] = RS_PROGRAM_PARAM_INPUT;
     tmp[3] = (uint32_t)attrElem.get();
 
-    ProgramVertex *pv = new ProgramVertex(rsc, shaderString.string(),
-                                          shaderString.length(), tmp, 4);
+    ProgramVertex *pv = new ProgramVertex(rsc, shaderString.string(), shaderString.length(),
+                                          NULL, 0, NULL, tmp, 4);
     Allocation *alloc = Allocation::createAllocation(rsc, inputType.get(),
                               RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS);
     pv->bindAllocation(rsc, alloc, 0);
@@ -229,10 +231,13 @@
 namespace android {
 namespace renderscript {
 
-RsProgramVertex rsi_ProgramVertexCreate(Context *rsc, const char * shaderText,
-                             size_t shaderLength, const uint32_t * params,
-                             size_t paramLength) {
-    ProgramVertex *pv = new ProgramVertex(rsc, shaderText, shaderLength, params, paramLength);
+RsProgramVertex rsi_ProgramVertexCreate(Context *rsc, const char * shaderText, size_t shaderLength,
+                                        const char** textureNames, size_t textureNamesCount,
+                                        const size_t *textureNamesLength,
+                                        const uint32_t * params, size_t paramLength) {
+    ProgramVertex *pv = new ProgramVertex(rsc, shaderText, shaderLength,
+                                          textureNames, textureNamesCount, textureNamesLength,
+                                          params, paramLength);
     pv->incUserRef();
     return pv;
 }
diff --git a/libs/rs/rsProgramVertex.h b/libs/rs/rsProgramVertex.h
index 5cfdd8b..67c2a88 100644
--- a/libs/rs/rsProgramVertex.h
+++ b/libs/rs/rsProgramVertex.h
@@ -27,8 +27,9 @@
 
 class ProgramVertex : public Program {
 public:
-    ProgramVertex(Context *,const char * shaderText, uint32_t shaderLength,
-                  const uint32_t * params, uint32_t paramLength);
+    ProgramVertex(Context *,const char * shaderText, size_t shaderLength,
+                  const char** textureNames, size_t textureNamesCount, const size_t *textureNamesLength,
+                  const uint32_t * params, size_t paramLength);
     virtual ~ProgramVertex();
 
     virtual void setup(Context *rsc, ProgramVertexState *state);
diff --git a/libs/rs/rs_hal.h b/libs/rs/rs_hal.h
index 7c9618a..800053a 100644
--- a/libs/rs/rs_hal.h
+++ b/libs/rs/rs_hal.h
@@ -172,14 +172,18 @@
 
     struct {
         bool (*init)(const Context *rsc, const ProgramVertex *pv,
-                     const char* shader, size_t shaderLen);
+                     const char* shader, size_t shaderLen,
+                     const char** textureNames, size_t textureNamesCount,
+                     const size_t *textureNamesLength);
         void (*setActive)(const Context *rsc, const ProgramVertex *pv);
         void (*destroy)(const Context *rsc, const ProgramVertex *pv);
     } vertex;
 
     struct {
         bool (*init)(const Context *rsc, const ProgramFragment *pf,
-                     const char* shader, size_t shaderLen);
+                     const char* shader, size_t shaderLen,
+                     const char** textureNames, size_t textureNamesCount,
+                     const size_t *textureNamesLength);
         void (*setActive)(const Context *rsc, const ProgramFragment *pf);
         void (*destroy)(const Context *rsc, const ProgramFragment *pf);
     } fragment;