Compiler - implement gl_DepthRange
TRAC #11380
Signed-off-by: Daniel Koch

Author:    Nicolas Capens <nicolas@transgaming.com>

git-svn-id: https://angleproject.googlecode.com/svn/trunk@16 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/libGLESv2/Context.cpp b/libGLESv2/Context.cpp
index bcc8368..9aada33 100644
--- a/libGLESv2/Context.cpp
+++ b/libGLESv2/Context.cpp
@@ -25,6 +25,9 @@
 #include "geometry/VertexDataManager.h"
 #include "geometry/dx9.h"
 
+#undef near
+#undef far
+
 namespace gl
 {
 Context::Context(const egl::Config *config)
@@ -792,6 +795,16 @@
         GLuint halfPixelSize = programObject->getUniformLocation("gl_HalfPixelSize");
         GLfloat xy[2] = {1.0f / description.Width, 1.0f / description.Height};
         programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
+
+        GLuint near = programObject->getUniformLocation("gl_DepthRange.near");
+        programObject->setUniform1fv(near, 1, &zNear);
+
+        GLuint far = programObject->getUniformLocation("gl_DepthRange.far");
+        programObject->setUniform1fv(far, 1, &zFar);
+
+        GLuint diff = programObject->getUniformLocation("gl_DepthRange.diff");
+        GLfloat zDiff = zFar - zNear;
+        programObject->setUniform1fv(diff, 1, &zDiff);
     }
 
     return true;
diff --git a/libGLESv2/Program.cpp b/libGLESv2/Program.cpp
index 04de91d..c580b9b 100644
--- a/libGLESv2/Program.cpp
+++ b/libGLESv2/Program.cpp
@@ -434,72 +434,17 @@
                 return;
             }
 
-            D3DXCONSTANTTABLE_DESC constantTableDescription;
-            D3DXCONSTANT_DESC constantDescription;
-            UINT descriptionCount = 1;
-
-            mConstantTablePS->GetDesc(&constantTableDescription);
-
-            for (unsigned int constantIndex = 0; constantIndex < constantTableDescription.Constants; constantIndex++)
+            if (!linkUniforms(mConstantTablePS))
             {
-                D3DXHANDLE constantHandle = mConstantTablePS->GetConstant(0, constantIndex);
-                mConstantTablePS->GetConstantDesc(constantHandle, &constantDescription, &descriptionCount);
-
-                UniformArray::iterator uniform = mUniforms.begin();
-
-                while (uniform != mUniforms.end())
-                {
-                    if ((*uniform)->name == constantDescription.Name)
-                    {
-                        UNREACHABLE();   // Redefinition; detect at compile
-                    }
-
-                    uniform++;
-                }
-
-                if (uniform == mUniforms.end())
-                {
-                    defineUniform(constantDescription);
-                }
+                return;
             }
 
-            mConstantTableVS->GetDesc(&constantTableDescription);
-
-            for (unsigned int constantIndex = 0; constantIndex < constantTableDescription.Constants; constantIndex++)
+            if (!linkUniforms(mConstantTableVS))
             {
-                D3DXHANDLE constantHandle = mConstantTableVS->GetConstant(0, constantIndex);
-                mConstantTableVS->GetConstantDesc(constantHandle, &constantDescription, &descriptionCount);
-
-                UniformArray::iterator uniform = mUniforms.begin();
-
-                while (uniform != mUniforms.end())
-                {
-                    if ((*uniform)->name == constantDescription.Name)
-                    {
-                        UNIMPLEMENTED();   // FIXME: Verify it's the same type as the fragment uniform
-
-                        if (true)
-                        {
-                            break;
-                        }
-                        else
-                        {
-                            return;
-                        }
-                    }
-
-                    uniform++;
-                }
-
-                if (uniform == mUniforms.end())
-                {
-                    defineUniform(constantDescription);
-                }
+                return;
             }
 
-            mLinked = true;
-
-            return;
+            mLinked = true;   // Success
         }
     }
 }
@@ -544,8 +489,97 @@
     return true;
 }
 
+bool Program::linkUniforms(ID3DXConstantTable *constantTable)
+{
+    D3DXCONSTANTTABLE_DESC constantTableDescription;
+    D3DXCONSTANT_DESC constantDescription;
+    UINT descriptionCount = 1;
+
+    constantTable->GetDesc(&constantTableDescription);
+
+    for (unsigned int constantIndex = 0; constantIndex < constantTableDescription.Constants; constantIndex++)
+    {
+        D3DXHANDLE constantHandle = constantTable->GetConstant(0, constantIndex);
+        constantTable->GetConstantDesc(constantHandle, &constantDescription, &descriptionCount);
+
+        if (!defineUniform(constantHandle, constantDescription))
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
 // Adds the description of a constant found in the binary shader to the list of uniforms
-void Program::defineUniform(const D3DXCONSTANT_DESC &constantDescription)
+// Returns true if succesful (uniform not already defined)
+bool Program::defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT_DESC &constantDescription, std::string name)
+{
+    switch(constantDescription.Class)
+    {
+      case D3DXPC_STRUCT:
+        {
+            for (unsigned int field = 0; field < constantDescription.StructMembers; field++)
+            {
+                D3DXHANDLE fieldHandle = mConstantTablePS->GetConstant(constantHandle, field);
+
+                D3DXCONSTANT_DESC fieldDescription;
+                UINT descriptionCount = 1;
+
+                mConstantTablePS->GetConstantDesc(fieldHandle, &fieldDescription, &descriptionCount);
+
+                if (!defineUniform(fieldHandle, fieldDescription, name + constantDescription.Name + "."))
+                {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+      case D3DXPC_SCALAR:
+      case D3DXPC_VECTOR:
+      case D3DXPC_MATRIX_COLUMNS:
+      case D3DXPC_OBJECT:
+        return defineUniform(constantDescription, name + constantDescription.Name);
+      default:
+        UNREACHABLE();
+        return false;
+    }
+}
+
+bool Program::defineUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name)
+{
+    Uniform *uniform = createUniform(constantDescription, name);
+
+    if(!uniform)
+    {
+        return false;
+    }
+
+    // Check if already defined
+    GLint location = getUniformLocation(name.c_str());
+    UniformType type = uniform->type;
+        
+    if (location >= 0)
+    {
+        delete uniform;
+
+        if (mUniforms[location]->type != type)
+        {
+            return false;
+        }
+        else
+        {
+            return true;
+        }
+    }
+
+    mUniforms.push_back(uniform);
+
+    return true;
+}
+
+Uniform *Program::createUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name)
 {
     if (constantDescription.Rows == 1)   // Vectors and scalars
     {
@@ -556,9 +590,7 @@
           case D3DXPT_BOOL:
             switch (constantDescription.Columns)
             {
-              case 1:
-                mUniforms.push_back(new Uniform(UNIFORM_1IV, constantDescription.Name, 1 * sizeof(GLint) * constantDescription.Elements));
-                break;
+              case 1: return new Uniform(UNIFORM_1IV, name, 1 * sizeof(GLint) * constantDescription.Elements);
               default:
                 UNIMPLEMENTED();   // FIXME
                 UNREACHABLE();
@@ -567,18 +599,10 @@
           case D3DXPT_FLOAT:
             switch (constantDescription.Columns)
             {
-              case 1:
-                mUniforms.push_back(new Uniform(UNIFORM_1FV, constantDescription.Name, 1 * sizeof(GLfloat) * constantDescription.Elements));
-                break;
-              case 2:
-                mUniforms.push_back(new Uniform(UNIFORM_2FV, constantDescription.Name, 2 * sizeof(GLfloat) * constantDescription.Elements));
-                break;
-              case 3:
-                mUniforms.push_back(new Uniform(UNIFORM_3FV, constantDescription.Name, 3 * sizeof(GLfloat) * constantDescription.Elements));
-                break;
-              case 4:
-                mUniforms.push_back(new Uniform(UNIFORM_4FV, constantDescription.Name, 4 * sizeof(GLfloat) * constantDescription.Elements));
-                break;
+              case 1: return new Uniform(UNIFORM_1FV, name, 1 * sizeof(GLfloat) * constantDescription.Elements);
+              case 2: return new Uniform(UNIFORM_2FV, name, 2 * sizeof(GLfloat) * constantDescription.Elements);
+              case 3: return new Uniform(UNIFORM_3FV, name, 3 * sizeof(GLfloat) * constantDescription.Elements);
+              case 4: return new Uniform(UNIFORM_4FV, name, 4 * sizeof(GLfloat) * constantDescription.Elements);
               default: UNREACHABLE();
             }
             break;
@@ -594,15 +618,9 @@
           case D3DXPT_FLOAT:
             switch (constantDescription.Rows)
             {
-              case 2:
-                mUniforms.push_back(new Uniform(UNIFORM_MATRIX_2FV, constantDescription.Name, 2 * 2 * sizeof(GLfloat) * constantDescription.Elements));
-                break;
-              case 3:
-                mUniforms.push_back(new Uniform(UNIFORM_MATRIX_3FV, constantDescription.Name, 3 * 3 * sizeof(GLfloat) * constantDescription.Elements));
-                break;
-              case 4:
-                mUniforms.push_back(new Uniform(UNIFORM_MATRIX_4FV, constantDescription.Name, 4 * 4 * sizeof(GLfloat) * constantDescription.Elements));
-                break;
+              case 2: return new Uniform(UNIFORM_MATRIX_2FV, name, 2 * 2 * sizeof(GLfloat) * constantDescription.Elements);
+              case 3: return new Uniform(UNIFORM_MATRIX_3FV, name, 3 * 3 * sizeof(GLfloat) * constantDescription.Elements);
+              case 4: return new Uniform(UNIFORM_MATRIX_4FV, name, 4 * 4 * sizeof(GLfloat) * constantDescription.Elements);
               default: UNREACHABLE();
             }
             break;
@@ -610,6 +628,8 @@
         }
     }
     else UNREACHABLE();
+
+    return 0;
 }
 
 bool Program::applyUniform1fv(GLint location, GLsizei count, const GLfloat *v)
diff --git a/libGLESv2/Program.h b/libGLESv2/Program.h
index d3c85bf..3e72d86 100644
--- a/libGLESv2/Program.h
+++ b/libGLESv2/Program.h
@@ -33,10 +33,9 @@
     UNIFORM_1IV
 };
 
-// Helper class representing a single shader uniform
-class Uniform
+// Helper struct representing a single shader uniform
+struct Uniform
 {
-  public:
     Uniform(UniformType type, const std::string &name, unsigned int bytes);
 
     ~Uniform();
@@ -45,9 +44,6 @@
     const std::string name;
     const unsigned int bytes;
     unsigned char *data;
-
-  private:
-    DISALLOW_COPY_AND_ASSIGN(Uniform);
 };
 
 class Program
@@ -95,7 +91,10 @@
     void unlink(bool destroy = false);
 
     bool linkAttributes();
-    void defineUniform(const D3DXCONSTANT_DESC &constantDescription);
+    bool linkUniforms(ID3DXConstantTable *constantTable);
+    bool defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT_DESC &constantDescription, std::string name = "");
+    bool defineUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name);
+    Uniform *createUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name);
     bool applyUniform1fv(GLint location, GLsizei count, const GLfloat *v);
     bool applyUniform2fv(GLint location, GLsizei count, const GLfloat *v);
     bool applyUniform3fv(GLint location, GLsizei count, const GLfloat *v);
diff --git a/libGLESv2/Shader.cpp b/libGLESv2/Shader.cpp
index 775a736..cbd3529 100644
--- a/libGLESv2/Shader.cpp
+++ b/libGLESv2/Shader.cpp
@@ -233,17 +233,18 @@
         while (*input != '}' && output)
         {
             char varyingName[100];
-            int semanticIndex;
+            unsigned int semanticIndex;
             int matches = sscanf(input, "%s : TEXCOORD%d;", varyingName, &semanticIndex);
 
             if (matches == 2)
             {
-                ASSERT(semanticIndex < 10 && semanticIndex < MAX_VARYING_VECTORS);
+                ASSERT(semanticIndex < MAX_VARYING_VECTORS);
                 char *varying = strstr(output, varyingName);
-                varying = strstr(varying, " : TEXCOORD0;");
-
-                if (output)
+                
+                if (varying)
                 {
+                    ASSERT(semanticIndex <= 9);   // Single character
+                    varying = strstr(varying, " : TEXCOORD0;");
                     varying[11] = '0' + semanticIndex;
                 }
                 else