Add support for the transpose parameter of the glUniformMatrix family of functions in ES3.

TRAC #22839

Signed-off-by: Geoff Lang
Signed-off-by: Shanon Woods
Author: Jamie Madill

git-svn-id: https://angleproject.googlecode.com/svn/branches/es3proto@2139 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/ProgramBinary.cpp b/src/libGLESv2/ProgramBinary.cpp
index 3aba5ed..1fba4de 100644
--- a/src/libGLESv2/ProgramBinary.cpp
+++ b/src/libGLESv2/ProgramBinary.cpp
@@ -490,8 +490,39 @@
     }
 }
 
+template<typename T>
+void expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
+{
+    int copyWidth = std::min(targetWidth, srcWidth);
+    int copyHeight = std::min(targetHeight, srcHeight);
+
+    for (int y = 0; y < copyHeight; y++)
+    {
+        for (int x = 0; x < copyWidth; x++)
+        {
+            target[y * targetWidth + x] = static_cast<T>(value[y * srcWidth + x]);
+        }
+    }
+    // clear unfilled right side
+    for (int y = 0; y < copyHeight; y++)
+    {
+        for (int x = copyWidth; x < targetWidth; x++)
+        {
+            target[y * targetWidth + x] = static_cast<T>(0);
+        }
+    }
+    // clear unfilled bottom.
+    for (int y = copyHeight; y < targetHeight; y++)
+    {
+        for (int x = 0; x < targetWidth; x++)
+        {
+            target[y * targetWidth + x] = static_cast<T>(0);
+        }
+    }
+}
+
 template <int cols, int rows>
-bool ProgramBinary::setUniformMatrixfv(GLint location, GLsizei count, const GLfloat *value, GLenum targetUniformType) 
+bool ProgramBinary::setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType) 
 {
     if (location < 0 || location >= (int)mUniformIndex.size())
     {
@@ -516,7 +547,15 @@
 
     for (int i = 0; i < count; i++)
     {
-        transposeMatrix<GLfloat>(target, value, 4, rows, rows, cols);
+        // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
+        if (transpose == GL_FALSE)
+        {
+            transposeMatrix<GLfloat>(target, value, 4, rows, rows, cols);
+        }
+        else
+        {
+            expandMatrix<GLfloat>(target, value, 4, rows, cols, rows);
+        }
         target += 4 * rows;
         value += cols * rows;
     }
@@ -524,49 +563,49 @@
     return true;
 }
 
-bool ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
+bool ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 {
-    return setUniformMatrixfv<2, 2>(location, count, value, GL_FLOAT_MAT2);
+    return setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
 }
 
-bool ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
+bool ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 {
-    return setUniformMatrixfv<3, 3>(location, count, value, GL_FLOAT_MAT3);
+    return setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
 }
 
-bool ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
+bool ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 {
-    return setUniformMatrixfv<4, 4>(location, count, value, GL_FLOAT_MAT4);
+    return setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
 }
 
-bool ProgramBinary::setUniformMatrix2x3fv(GLint location, GLsizei count, const GLfloat *value)
+bool ProgramBinary::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 {
-    return setUniformMatrixfv<2, 3>(location, count, value, GL_FLOAT_MAT2x3);
+    return setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
 }
 
-bool ProgramBinary::setUniformMatrix3x2fv(GLint location, GLsizei count, const GLfloat *value)
+bool ProgramBinary::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 {
-    return setUniformMatrixfv<3, 2>(location, count, value, GL_FLOAT_MAT3x2);
+    return setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
 }
 
-bool ProgramBinary::setUniformMatrix2x4fv(GLint location, GLsizei count, const GLfloat *value)
+bool ProgramBinary::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 {
-    return setUniformMatrixfv<2, 4>(location, count, value, GL_FLOAT_MAT2x4);
+    return setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
 }
 
-bool ProgramBinary::setUniformMatrix4x2fv(GLint location, GLsizei count, const GLfloat *value)
+bool ProgramBinary::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 {
-    return setUniformMatrixfv<4, 2>(location, count, value, GL_FLOAT_MAT4x2);
+    return setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
 }
 
-bool ProgramBinary::setUniformMatrix3x4fv(GLint location, GLsizei count, const GLfloat *value)
+bool ProgramBinary::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 {
-    return setUniformMatrixfv<3, 4>(location, count, value, GL_FLOAT_MAT3x4);
+    return setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
 }
 
-bool ProgramBinary::setUniformMatrix4x3fv(GLint location, GLsizei count, const GLfloat *value)
+bool ProgramBinary::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 {
-    return setUniformMatrixfv<4, 3>(location, count, value, GL_FLOAT_MAT4x3);
+    return setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
 }
 
 bool ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v)