Implemented aliased attributes support
TRAC #11092
Signed-off-by: Shannon Woods
Signed-off-by: Daniel Koch

Author:    Nicolas Capens

git-svn-id: https://angleproject.googlecode.com/svn/trunk@177 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Program.cpp b/src/libGLESv2/Program.cpp
index f8d14b1..534eabb 100644
--- a/src/libGLESv2/Program.cpp
+++ b/src/libGLESv2/Program.cpp
@@ -37,11 +37,6 @@
     mConstantTablePS = NULL;
     mConstantTableVS = NULL;
 
-    for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
-    {
-        mAttributeName[index] = NULL;
-    }
-
     mPixelHLSL = NULL;
     mVertexHLSL = NULL;
     mInfoLog = NULL;
@@ -131,40 +126,36 @@
 {
     if (index < MAX_VERTEX_ATTRIBS)
     {
-        delete[] mAttributeName[index];
-        mAttributeName[index] = new char[strlen(name) + 1];
-        strcpy(mAttributeName[index], name);
+        for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+        {
+            mAttributeBinding[i].erase(name);
+        }
+
+        mAttributeBinding[index].insert(name);
     }
 }
 
 GLuint Program::getAttributeLocation(const char *name)
 {
-    for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
+    if (name)
     {
-        if (mAttributeName[index] && strcmp(mAttributeName[index], name) == 0)
+        for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
         {
-            return index;
+            if (mLinkedAttribute[index] == std::string(name))
+            {
+                return index;
+            }
         }
     }
 
     return -1;
 }
 
-bool Program::isActiveAttribute(int attributeIndex)
+int Program::getSemanticIndex(int attributeIndex)
 {
     if (attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS)
     {
-        return mInputMapping[attributeIndex] != -1;
-    }
-
-    return false;
-}
-
-int Program::getInputMapping(int attributeIndex)
-{
-    if (attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS)
-    {
-        return mInputMapping[attributeIndex];
+        return mSemanticIndex[attributeIndex];
     }
 
     return -1;
@@ -951,6 +942,8 @@
     {
         if (pixelVaryings[in].link < 0)
         {
+            appendToInfoLog("Pixel varying (%s) does not match any vertex varying", pixelVaryings[in].name);
+
             return false;
         }
     }
@@ -1043,43 +1036,70 @@
 // Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
 bool Program::linkAttributes()
 {
+    // Link attributes that have a binding location
     for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
     {
         const char *name = mVertexShader->getAttributeName(attributeIndex);
+        int location = getAttributeBinding(name);
 
-        if (name)
+        if (location != -1)   // Set by glBindAttribLocation
         {
-            GLuint location = getAttributeLocation(name);
-
-            if (location == -1)   // Not set by glBindAttribLocation
+            if (!mLinkedAttribute[location].empty())
             {
-                int availableIndex = 0;
-
-                while (availableIndex < MAX_VERTEX_ATTRIBS && mAttributeName[availableIndex] && mVertexShader->isActiveAttribute(mAttributeName[availableIndex]))
-                {
-                    availableIndex++;
-                }
-
-                if (availableIndex == MAX_VERTEX_ATTRIBS)
-                {
-                    return false;   // Fail to link
-                }
-
-                delete[] mAttributeName[availableIndex];
-                mAttributeName[availableIndex] = new char[strlen(name) + 1];   // FIXME: Check allocation
-                strcpy(mAttributeName[availableIndex], name);
+                // Multiple active attributes bound to the same location; not an error
             }
+
+            mLinkedAttribute[location] = name;
+        }
+    }
+
+    // Link attributes that don't have a binding location
+    for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS + 1; attributeIndex++)
+    {
+        const char *name = mVertexShader->getAttributeName(attributeIndex);
+        int location = getAttributeBinding(name);
+
+        if (location == -1)   // Not set by glBindAttribLocation
+        {
+            int availableIndex = 0;
+
+            while (availableIndex < MAX_VERTEX_ATTRIBS && !mLinkedAttribute[availableIndex].empty())
+            {
+                availableIndex++;
+            }
+
+            if (availableIndex == MAX_VERTEX_ATTRIBS)
+            {
+                appendToInfoLog("Too many active attributes (%s)", name);
+
+                return false;   // Fail to link
+            }
+
+            mLinkedAttribute[availableIndex] = name;
         }
     }
 
     for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
     {
-        mInputMapping[attributeIndex] = mVertexShader->getInputMapping(mAttributeName[attributeIndex]);
+        mSemanticIndex[attributeIndex] = mVertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].c_str());
     }
 
     return true;
 }
 
+int Program::getAttributeBinding(const char *name)
+{
+    for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
+    {
+        if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end())
+        {
+            return location;
+        }
+    }
+
+    return -1;
+}
+
 bool Program::linkUniforms(ID3DXConstantTable *constantTable)
 {
     D3DXCONSTANTTABLE_DESC constantTableDescription;
@@ -1729,13 +1749,20 @@
     return true;
 }
 
-void Program::appendToInfoLog(const char *info)
+void Program::appendToInfoLog(const char *format, ...)
 {
-    if (!info)
+    if (!format)
     {
         return;
     }
 
+    char info[1024];
+
+    va_list vararg;
+    va_start(vararg, format);
+    vsnprintf(info, sizeof(info), format, vararg);
+    va_end(vararg);
+
     size_t infoLength = strlen(info);
 
     if (!mInfoLog)
@@ -1771,12 +1798,6 @@
             mVertexShader->detach();
             mVertexShader = NULL;
         }
-
-        for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
-        {
-            delete[] mAttributeName[index];
-            mAttributeName[index] = NULL;
-        }
     }
 
     if (mPixelExecutable)
@@ -1805,7 +1826,8 @@
 
     for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
     {
-        mInputMapping[index] = 0;
+        mLinkedAttribute[index].clear();
+        mSemanticIndex[index] = -1;
     }
 
     for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)