Fixing renderscript uniform binding bugs.
Working on custom shaders.

Change-Id: I0d51e879e1c2b46ef5ab696b35162898f4196fc8
diff --git a/libs/rs/java/Samples/res/raw/shaderf.glsl b/libs/rs/java/Samples/res/raw/shaderf.glsl
new file mode 100644
index 0000000..81452ab
--- /dev/null
+++ b/libs/rs/java/Samples/res/raw/shaderf.glsl
@@ -0,0 +1,18 @@
+
+varying lowp float light0_Diffuse;
+varying lowp float light0_Specular;
+varying lowp float light1_Diffuse;
+varying lowp float light1_Specular;
+
+void main() {
+   vec2 t0 = varTex0.xy;
+   lowp vec4 col = texture2D(uni_Tex0, t0).rgba;
+   /*col = col * (light0_Diffuse * UNI_light0_DiffuseColor + light1_Diffuse * UNI_light1_DiffuseColor);
+   col += light0_Specular * UNI_light0_SpecularColor;
+   col += light1_Specular * UNI_light1_SpecularColor;*/
+   col = col * (light0_Diffuse + light1_Diffuse);
+   col += light0_Specular;
+   col += light1_Specular;
+   gl_FragColor = col;
+}
+
diff --git a/libs/rs/java/Samples/res/raw/shaderv.glsl b/libs/rs/java/Samples/res/raw/shaderv.glsl
new file mode 100644
index 0000000..7f61197
--- /dev/null
+++ b/libs/rs/java/Samples/res/raw/shaderv.glsl
@@ -0,0 +1,42 @@
+varying float light0_Diffuse;
+varying float light0_Specular;
+varying float light1_Diffuse;
+varying float light1_Specular;
+
+/*
+rs_matrix4x4 model;
+ float3 light0_Posision;
+ float light0_Diffuse;
+ float light0_Specular;
+ float light0_CosinePower;
+
+ float3 light1_Posision;
+ float light1_Diffuse;
+ float light1_Specular;
+ float light1_CosinePower;
+*/
+
+// This is where actual shader code begins
+void main() {
+   vec4 worldPos = UNI_model * ATTRIB_position;
+   gl_Position = UNI_MVP * worldPos;
+
+   mat3 model3 = mat3(UNI_model[0].xyz, UNI_model[1].xyz, UNI_model[2].xyz);
+   vec3 worldNorm = model3 * ATTRIB_normal;
+   vec3 V = normalize(-worldPos.xyz);
+
+   vec3 light0Vec = normalize(UNI_light0_Posision - worldPos.xyz);
+   vec3 light0R = reflect(light0Vec, worldNorm);
+   light0_Diffuse = clamp(dot(worldNorm, light0Vec), 0.0, 1.0) * UNI_light0_Diffuse;
+   float light0Spec = clamp(dot(light0R, V), 0.001, 1.0);
+   light0_Specular = pow(light0Spec, UNI_light0_CosinePower) * UNI_light0_Specular;
+
+   vec3 light1Vec = normalize(UNI_light1_Posision - worldPos.xyz);
+   vec3 light1R = reflect(light1Vec, worldNorm);
+   light1_Diffuse = clamp(dot(worldNorm, light1Vec), 0.0, 1.0) * UNI_light1_Diffuse;
+   float light1Spec = clamp(dot(light1R, V), 0.001, 1.0);
+   light1_Specular = pow(light1Spec, UNI_light1_CosinePower) * UNI_light1_Specular;
+
+   gl_PointSize = 1.0;
+   varTex0 = ATTRIB_texture0;
+}
diff --git a/libs/rs/java/Samples/res/raw/torus.a3d b/libs/rs/java/Samples/res/raw/torus.a3d
index 610f095..d09bc13 100644
--- a/libs/rs/java/Samples/res/raw/torus.a3d
+++ b/libs/rs/java/Samples/res/raw/torus.a3d
Binary files differ
diff --git a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java
index 8eff455..e76e740 100644
--- a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java
+++ b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java
@@ -65,6 +65,13 @@
     private ProgramVertex mProgVertex;
     private ProgramVertex.MatrixAllocation mPVA;
 
+    // Custom shaders
+    private ProgramVertex mProgVertexCustom;
+    private ProgramVertex.MatrixAllocation mPVACustom;
+    private ProgramFragment mProgFragmentCustom;
+    private ScriptField_VertexShaderConstants_s mVSConst;
+    private ScriptField_FragentShaderConstants_s mFSConst;
+
     private ProgramRaster mCullBack;
     private ProgramRaster mCullFront;
 
@@ -178,6 +185,42 @@
         mScript.set_gProgVertex(mProgVertex);
     }
 
+    private void initCustomShaders() {
+        mVSConst = new ScriptField_VertexShaderConstants_s(mRS, 1);
+        mFSConst = new ScriptField_FragentShaderConstants_s(mRS, 1);
+
+        mScript.bind_gVSConstants(mVSConst);
+        mScript.bind_gFSConstants(mFSConst);
+
+        // Initialize the shader builder
+        ProgramVertex.ShaderBuilder pvbCustom = new ProgramVertex.ShaderBuilder(mRS);
+        // Specify the resource that contains the shader string
+        pvbCustom.setShader(mRes, R.raw.shaderv);
+        // Use a script field to spcify the input layout
+        pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
+        // Define the constant input layout
+        pvbCustom.addConstant(mVSConst.getAllocation().getType());
+        mProgVertexCustom = pvbCustom.create();
+        // Bind the source of constant data
+        mProgVertexCustom.bindConstants(mVSConst.getAllocation(), 1);
+        mPVACustom = new ProgramVertex.MatrixAllocation(mRS);
+        mProgVertexCustom.bindAllocation(mPVACustom);
+
+        ProgramFragment.ShaderBuilder pfbCustom = new ProgramFragment.ShaderBuilder(mRS);
+        // Specify the resource that contains the shader string
+        pfbCustom.setShader(mRes, R.raw.shaderf);
+        //Tell the builder how many textures we have
+        pfbCustom.setTextureCount(1);
+        // Define the constant input layout
+        pfbCustom.addConstant(mFSConst.getAllocation().getType());
+        mProgFragmentCustom = pfbCustom.create();
+        // Bind the source of constant data
+        mProgFragmentCustom.bindConstants(mFSConst.getAllocation(), 1);
+
+        mScript.set_gProgVertexCustom(mProgVertexCustom);
+        mScript.set_gProgFragmentCustom(mProgFragmentCustom);
+    }
+
     private Allocation loadTextureRGB(int id) {
         final Allocation allocation = Allocation.createFromBitmapResource(mRS, mRes,
                 id, Element.RGB_565(mRS), true);
@@ -274,6 +317,7 @@
         loadImages();
         initMesh();
         initProgramRaster();
+        initCustomShaders();
 
         mRS.contextBindRootScript(mScript);
     }
diff --git a/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs b/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs
index 68d9d3c..165a6d7 100644
--- a/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs
+++ b/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs
@@ -17,6 +17,7 @@
 #pragma rs java_package_name(com.android.samples)
 
 #include "rs_graphics.rsh"
+#include "shader_def.rsh"
 
 rs_program_vertex gProgVertex;
 rs_program_fragment gProgFragmentColor;
@@ -51,6 +52,15 @@
 rs_program_raster gCullBack;
 rs_program_raster gCullFront;
 
+// Custom vertex shader compunents
+VertexShaderConstants *gVSConstants;
+FragentShaderConstants *gFSConstants;
+// Export these out to easily set the inputs to shader
+VertexShaderInputs *gVSInputs;
+// Custom shaders we use for lighting
+rs_program_vertex gProgVertexCustom;
+rs_program_fragment gProgFragmentCustom;
+
 #pragma rs export_var(gProgVertex, gProgFragmentColor, gProgFragmentTexture)
 #pragma rs export_var(gProgStoreBlendNoneDepth, gProgStoreBlendNone, gProgStoreBlendAlpha, gProgStoreBlendAdd)
 #pragma rs export_var(gTexOpaque, gTexTorus, gTexTransparent)
@@ -58,6 +68,7 @@
 #pragma rs export_var(gFontSans, gFontSerif, gFontSerifBold, gFontSerifItalic, gFontSerifBoldItalic, gFontMono)
 #pragma rs export_var(gLinearClamp, gLinearWrap, gMipLinearWrap, gNearestClamp)
 #pragma rs export_var(gCullBack, gCullFront)
+#pragma rs export_var(gVSConstants, gFSConstants, gVSInputs, gProgVertexCustom, gProgFragmentCustom)
 
 //What we are showing
 #pragma rs export_var(gDisplayMode)
@@ -274,7 +285,7 @@
 
 float gTorusRotation = 0;
 
-void displayCullingSamplers() {
+void displayCullingSamples() {
     rsgBindProgramVertex(gProgVertex);
     // Setup the projectioni matrix with 60 degree field of view
     rs_matrix4x4 proj;
@@ -315,6 +326,94 @@
     rsgDrawText("Displaying mesh front/back face culling", 10, rsgGetHeight() - 10);
 }
 
+float gLight0Rotation = 0;
+float gLight1Rotation = 0;
+
+void setupCustomShaderLights() {
+    float4 light0Pos = {-5.0f, 5.0f, -10.0f, 1.0f};
+    float4 light1Pos = {2.0f, 5.0f, 15.0f, 1.0f};
+    float3 light0DiffCol = {0.9f, 0.7f, 0.7f};
+    float3 light0SpecCol = {0.9f, 0.8f, 0.8f};
+    float3 light1DiffCol = {0.7f, 0.7f, 0.9f};
+    float3 light1SpecCol = {0.8f, 0.8f, 0.9f};
+
+    gLight0Rotation += 150.0f * rsGetDt();
+    if(gLight0Rotation > 360.0f) {
+        gLight0Rotation -= 360.0f;
+    }
+    gLight1Rotation -= 50.0f * rsGetDt();
+    if(gLight1Rotation > 360.0f) {
+        gLight1Rotation -= 360.0f;
+    }
+
+    rs_matrix4x4 l0Mat;
+    rsMatrixLoadRotate(&l0Mat, gLight0Rotation, 1.0f, 0.0f, 0.0f);
+    light0Pos = rsMatrixMultiply(&l0Mat, light0Pos);
+    rs_matrix4x4 l1Mat;
+    rsMatrixLoadRotate(&l1Mat, gLight1Rotation, 0.0f, 0.0f, 1.0f);
+    light1Pos = rsMatrixMultiply(&l1Mat, light1Pos);
+
+    // Set light 0 properties
+    gVSConstants->light0_Posision.x = light0Pos.x;
+    gVSConstants->light0_Posision.y = light0Pos.y;
+    gVSConstants->light0_Posision.z = light0Pos.z;
+    gVSConstants->light0_Diffuse = 1.0f;
+    gVSConstants->light0_Specular = 0.5f;
+    gVSConstants->light0_CosinePower = 70.0f;
+    // Set light 1 properties
+    gVSConstants->light1_Posision.x = light1Pos.x;
+    gVSConstants->light1_Posision.y = light1Pos.y;
+    gVSConstants->light1_Posision.z = light1Pos.z;
+    gVSConstants->light1_Diffuse = 1.0f;
+    gVSConstants->light1_Specular = 0.7f;
+    gVSConstants->light1_CosinePower = 50.0f;
+
+    // Update fragmetn shader constants
+    // Set light 0 colors
+    gFSConstants->light0_DiffuseColor = light0DiffCol;
+    gFSConstants->light0_SpecularColor = light0SpecCol;
+    // Set light 1 colors
+    gFSConstants->light1_DiffuseColor = light1DiffCol;
+    gFSConstants->light1_SpecularColor = light1SpecCol;
+}
+
+void displayCustomShaderSamples() {
+
+    // Update vertex shader constants
+    // Load model matrix
+    // Aplly a rotation to our mesh
+    gTorusRotation += 50.0f * rsGetDt();
+    if(gTorusRotation > 360.0f) {
+        gTorusRotation -= 360.0f;
+    }
+
+    // Position our model on the screen
+    rsMatrixLoadTranslate(&gVSConstants->model, 0.0f, 0.0f, -10.0f);
+    rsMatrixRotate(&gVSConstants->model, gTorusRotation, 1.0f, 0.0f, 0.0f);
+    setupCustomShaderLights();
+
+    rsgBindProgramVertex(gProgVertexCustom);
+    // Setup the projectioni matrix with 60 degree field of view
+    rs_matrix4x4 proj;
+    float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
+    rsMatrixLoadPerspective(&proj, 30.0f, aspect, 0.1f, 100.0f);
+    rsgProgramVertexLoadProjectionMatrix(&proj);
+
+    // Fragment shader with texture
+    rsgBindProgramStore(gProgStoreBlendNoneDepth);
+    rsgBindProgramFragment(gProgFragmentCustom);
+    rsgBindSampler(gProgFragmentCustom, 0, gLinearClamp);
+    rsgBindTexture(gProgFragmentCustom, 0, gTexTorus);
+
+    // Use back face culling
+    rsgBindProgramRaster(gCullBack);
+    rsgDrawMesh(gTorusMesh);
+
+    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
+    rsgBindFont(gFontMono);
+    rsgDrawText("Custom shader sample", 10, rsgGetHeight() - 10);
+}
+
 int root(int launchID) {
 
     rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f);
@@ -337,7 +436,10 @@
         displayTextureSamplers();
         break;
     case 5:
-        displayCullingSamplers();
+        displayCullingSamples();
+        break;
+    case 6:
+        displayCustomShaderSamples();
         break;
     }
 
diff --git a/libs/rs/java/Samples/src/com/android/samples/shader_def.rsh b/libs/rs/java/Samples/src/com/android/samples/shader_def.rsh
new file mode 100644
index 0000000..1b697ca
--- /dev/null
+++ b/libs/rs/java/Samples/src/com/android/samples/shader_def.rsh
@@ -0,0 +1,47 @@
+// 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.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.samples)
+
+typedef struct VertexShaderConstants_s {
+    rs_matrix4x4 model;
+    float3 light0_Posision;
+    float light0_Diffuse;
+    float light0_Specular;
+    float light0_CosinePower;
+
+    float3 light1_Posision;
+    float light1_Diffuse;
+    float light1_Specular;
+    float light1_CosinePower;
+
+} VertexShaderConstants;
+
+typedef struct FragentShaderConstants_s {
+    float3 light0_DiffuseColor;
+    float3 light0_SpecularColor;
+
+    float3 light1_DiffuseColor;
+    float3 light1_SpecularColor;
+
+} FragentShaderConstants;
+
+typedef struct VertexShaderInputs_s {
+    float4 position;
+    float3 normal;
+    float4 texture0;
+} VertexShaderInputs;
+
diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp
index aee4133..8468e26 100644
--- a/libs/rs/rsProgramVertex.cpp
+++ b/libs/rs/rsProgramVertex.cpp
@@ -146,13 +146,24 @@
 
                 // Cannot be complex
                 rsAssert(!f->getFieldCount());
-                switch(f->getComponent().getVectorSize()) {
-                case 1: mShader.append("uniform float UNI_"); break;
-                case 2: mShader.append("uniform vec2 UNI_"); break;
-                case 3: mShader.append("uniform vec3 UNI_"); break;
-                case 4: mShader.append("uniform vec4 UNI_"); break;
-                default:
-                    rsAssert(0);
+                if(f->getType() == RS_TYPE_MATRIX_4X4) {
+                    mShader.append("uniform mat4 UNI_");
+                }
+                else if(f->getType() == RS_TYPE_MATRIX_3X3) {
+                    mShader.append("uniform mat3 UNI_");
+                }
+                else if(f->getType() == RS_TYPE_MATRIX_2X2) {
+                    mShader.append("uniform mat2 UNI_");
+                }
+                else {
+                    switch(f->getComponent().getVectorSize()) {
+                    case 1: mShader.append("uniform float UNI_"); break;
+                    case 2: mShader.append("uniform vec2 UNI_"); break;
+                    case 3: mShader.append("uniform vec3 UNI_"); break;
+                    case 4: mShader.append("uniform vec4 UNI_"); break;
+                    default:
+                        rsAssert(0);
+                    }
                 }
 
                 mShader.append(fn);
@@ -250,41 +261,53 @@
             const Element *f = e->getField(field);
             uint32_t offset = e->getFieldOffsetBytes(field);
             int32_t slot = sc->vtxUniformSlot(uidx);
+            const char *fieldName = e->getFieldName(field);
 
             const float *fd = reinterpret_cast<const float *>(&data[offset]);
 
-            //LOGE("Uniform  slot=%i, offset=%i, constant=%i, field=%i, uidx=%i", slot, offset, ct, field, uidx);
+            // If this field is padding, skip it
+            if(fieldName[0] == '#') {
+                continue;
+            }
+
+            //LOGE("Uniform  slot=%i, offset=%i, constant=%i, field=%i, uidx=%i, name=%s", slot, offset, ct, field, uidx, fieldName);
             if (slot >= 0) {
-                switch(f->getComponent().getVectorSize()) {
-                case 1:
-                    //LOGE("Uniform 1 = %f", fd[0]);
-                    glUniform1fv(slot, 1, fd);
-                    break;
-                case 2:
-                    //LOGE("Uniform 2 = %f %f", fd[0], fd[1]);
-                    glUniform2fv(slot, 1, fd);
-                    break;
-                case 3:
-                    //LOGE("Uniform 3 = %f %f %f", fd[0], fd[1], fd[2]);
-                    glUniform3fv(slot, 1, fd);
-                    break;
-                case 4:
-                    //LOGE("Uniform 4 = %f %f %f %f", fd[0], fd[1], fd[2], fd[3]);
-                    glUniform4fv(slot, 1, fd);
-                    break;
-                default:
-                    rsAssert(0);
+                if(f->getType() == RS_TYPE_MATRIX_4X4) {
+                    glUniformMatrix4fv(slot, 1, GL_FALSE, fd);
+                }
+                else if(f->getType() == RS_TYPE_MATRIX_3X3) {
+                    glUniformMatrix3fv(slot, 1, GL_FALSE, fd);
+                }
+                else if(f->getType() == RS_TYPE_MATRIX_2X2) {
+                    glUniformMatrix2fv(slot, 1, GL_FALSE, fd);
+                }
+                else {
+                    switch(f->getComponent().getVectorSize()) {
+                    case 1:
+                        //LOGE("Uniform 1 = %f", fd[0]);
+                        glUniform1fv(slot, 1, fd);
+                        break;
+                    case 2:
+                        //LOGE("Uniform 2 = %f %f", fd[0], fd[1]);
+                        glUniform2fv(slot, 1, fd);
+                        break;
+                    case 3:
+                        //LOGE("Uniform 3 = %f %f %f", fd[0], fd[1], fd[2]);
+                        glUniform3fv(slot, 1, fd);
+                        break;
+                    case 4:
+                        //LOGE("Uniform 4 = %f %f %f %f", fd[0], fd[1], fd[2], fd[3]);
+                        glUniform4fv(slot, 1, fd);
+                        break;
+                    default:
+                        rsAssert(0);
+                    }
                 }
             }
             uidx ++;
         }
     }
 
-    for (uint32_t ct=0; ct < mConstantCount; ct++) {
-        uint32_t glSlot = sc->vtxUniformSlot(ct + 1);
-
-    }
-
     state->mLast.set(this);
     rsc->checkError("ProgramVertex::setupGL2");
 }
@@ -340,7 +363,8 @@
         const Element *ce = e->getField(ct);
         if (ce->getFieldCount()) {
             initAddUserElement(ce, names, count, prefix);
-        } else {
+        }
+        else if(e->getFieldName(ct)[0] != '#') {
             String8 tmp(prefix);
             tmp.append(e->getFieldName(ct));
             names[*count].setTo(tmp.string());
diff --git a/libs/rs/rsVertexArray.cpp b/libs/rs/rsVertexArray.cpp
index 001927c..075a70d 100644
--- a/libs/rs/rsVertexArray.cpp
+++ b/libs/rs/rsVertexArray.cpp
@@ -129,7 +129,7 @@
 
     rsc->checkError("VertexArray::setupGL2 disabled");
     for (uint32_t ct=0; ct < mCount; ct++) {
-        uint32_t slot = 0;
+        int32_t slot = 0;
 
         if (mAttribs[ct].name[0] == '#') {
             continue;
@@ -150,6 +150,9 @@
                 continue;
             }
         }
+        if(slot < 0) {
+            continue;
+        }
 
         //logAttrib(ct, slot);
         glEnableVertexAttribArray(slot);