Bug 1136494 - Update uniform setters. - r=mtseng draft
authorJeff Gilbert <jgilbert@mozilla.com>
Thu, 14 Jul 2016 12:13:47 -0700
changeset 387739 e8d72bb5a06ce79a85b2ac0596da243f7ae0154a
parent 387738 fbc390f4ef367ae032e117ef38c78c333e076d08
child 387740 cfc4efac4a8fab48b6873c4fc490c130a739b9b5
push id23062
push userbmo:jgilbert@mozilla.com
push dateThu, 14 Jul 2016 19:33:51 +0000
reviewersmtseng
bugs1136494
milestone50.0a1
Bug 1136494 - Update uniform setters. - r=mtseng MozReview-Commit-ID: 4jZrqgu4qQm
dom/canvas/WebGL2Context.h
dom/canvas/WebGL2ContextUniforms.cpp
dom/canvas/WebGLContext.h
dom/canvas/WebGLContextGL.cpp
dom/canvas/WebGLContextValidate.cpp
--- a/dom/canvas/WebGL2Context.h
+++ b/dom/canvas/WebGL2Context.h
@@ -137,121 +137,78 @@ public:
     GLint GetFragDataLocation(WebGLProgram* program, const nsAString& name);
 
 
     // -------------------------------------------------------------------------
     // Uniforms and attributes - WebGL2ContextUniforms.cpp
     void VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
 
     // GL 3.0 & ES 3.0
-    void Uniform1ui(WebGLUniformLocation* location, GLuint v0);
-    void Uniform2ui(WebGLUniformLocation* location, GLuint v0, GLuint v1);
-    void Uniform3ui(WebGLUniformLocation* location, GLuint v0, GLuint v1, GLuint v2);
-    void Uniform4ui(WebGLUniformLocation* location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+    void Uniform1ui(WebGLUniformLocation* loc, GLuint v0);
+    void Uniform2ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1);
+    void Uniform3ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2);
+    void Uniform4ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2,
+                    GLuint v3);
+
+    ////////////////
 
-private:
-    void Uniform1uiv_base(WebGLUniformLocation* loc, size_t arrayLength, const GLuint* data);
-    void Uniform2uiv_base(WebGLUniformLocation* loc, size_t arrayLength, const GLuint* data);
-    void Uniform3uiv_base(WebGLUniformLocation* loc, size_t arrayLength, const GLuint* data);
-    void Uniform4uiv_base(WebGLUniformLocation* loc, size_t arrayLength, const GLuint* data);
+protected:
+    typedef Arr<GLuint, dom::Uint32Array> UintArr;
+
+    void UniformNuiv(const char* funcName, uint8_t N, WebGLUniformLocation* loc,
+                     const UintArr& arr);
+
+    //////
 
 public:
-    void Uniform1uiv(WebGLUniformLocation* loc, const dom::Sequence<GLuint>& arr) {
-        Uniform1uiv_base(loc, arr.Length(), arr.Elements());
-    }
-    void Uniform2uiv(WebGLUniformLocation* loc, const dom::Sequence<GLuint>& arr) {
-        Uniform2uiv_base(loc, arr.Length(), arr.Elements());
+    template<typename T>
+    void Uniform1uiv(WebGLUniformLocation* loc, const T& arr) {
+        UniformNuiv("uniform1uiv", 1, loc, UintArr(arr));
     }
-    void Uniform3uiv(WebGLUniformLocation* loc, const dom::Sequence<GLuint>& arr) {
-        Uniform3uiv_base(loc, arr.Length(), arr.Elements());
-    }
-    void Uniform4uiv(WebGLUniformLocation* loc, const dom::Sequence<GLuint>& arr) {
-        Uniform4uiv_base(loc, arr.Length(), arr.Elements());
+    template<typename T>
+    void Uniform2uiv(WebGLUniformLocation* loc, const T& arr) {
+        UniformNuiv("uniform2uiv", 2, loc, UintArr(arr));
     }
-    void Uniform1uiv(WebGLUniformLocation* loc, const dom::Uint32Array& arr) {
-        arr.ComputeLengthAndData();
-        Uniform1uiv_base(loc, arr.Length(), arr.Data());
-    }
-    void Uniform2uiv(WebGLUniformLocation* loc, const dom::Uint32Array& arr) {
-        arr.ComputeLengthAndData();
-        Uniform2uiv_base(loc, arr.Length(), arr.Data());
+    template<typename T>
+    void Uniform3uiv(WebGLUniformLocation* loc, const T& arr) {
+        UniformNuiv("uniform3uiv", 3, loc, UintArr(arr));
     }
-    void Uniform3uiv(WebGLUniformLocation* loc, const dom::Uint32Array& arr) {
-        arr.ComputeLengthAndData();
-        Uniform3uiv_base(loc, arr.Length(), arr.Data());
-    }
-    void Uniform4uiv(WebGLUniformLocation* loc, const dom::Uint32Array& arr) {
-        arr.ComputeLengthAndData();
-        Uniform4uiv_base(loc, arr.Length(), arr.Data());
+    template<typename T>
+    void Uniform4uiv(WebGLUniformLocation* loc, const T& arr) {
+        UniformNuiv("uniform4uiv", 4, loc, UintArr(arr));
     }
 
-private:
-    void UniformMatrix2x3fv_base(WebGLUniformLocation* loc, bool transpose,
-                                 size_t arrayLength, const GLfloat* data);
-    void UniformMatrix3x2fv_base(WebGLUniformLocation* loc, bool transpose,
-                                 size_t arrayLength, const GLfloat* data);
-    void UniformMatrix2x4fv_base(WebGLUniformLocation* loc, bool transpose,
-                                 size_t arrayLength, const GLfloat* data);
-    void UniformMatrix4x2fv_base(WebGLUniformLocation* loc, bool transpose,
-                                 size_t arrayLength, const GLfloat* data);
-    void UniformMatrix3x4fv_base(WebGLUniformLocation* loc, bool transpose,
-                                 size_t arrayLength, const GLfloat* data);
-    void UniformMatrix4x3fv_base(WebGLUniformLocation* loc, bool transpose,
-                                 size_t arrayLength, const GLfloat* data);
+    //////
 
-public:
-    // GL 2.1 & ES 3.0
-    void UniformMatrix2x3fv(WebGLUniformLocation* loc, bool transpose, const dom::Sequence<GLfloat>& value){
-        UniformMatrix2x3fv_base(loc, transpose, value.Length(), value.Elements());
+    template<typename T>
+    void UniformMatrix2x3fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
+        UniformMatrixAxBfv("uniformMatrix2x3fv", 2, 3, loc, transpose, FloatArr(arr));
     }
-    void UniformMatrix2x4fv(WebGLUniformLocation* loc, bool transpose, const dom::Sequence<GLfloat>& value){
-        UniformMatrix2x4fv_base(loc, transpose, value.Length(), value.Elements());
+    template<typename T>
+    void UniformMatrix2x4fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
+        UniformMatrixAxBfv("uniformMatrix2x4fv", 2, 4, loc, transpose, FloatArr(arr));
+    }
+    template<typename T>
+    void UniformMatrix3x2fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
+        UniformMatrixAxBfv("uniformMatrix3x2fv", 3, 2, loc, transpose, FloatArr(arr));
     }
-    void UniformMatrix3x2fv(WebGLUniformLocation* loc, bool transpose, const dom::Sequence<GLfloat>& value){
-        UniformMatrix3x2fv_base(loc, transpose, value.Length(), value.Elements());
-    }
-    void UniformMatrix3x4fv(WebGLUniformLocation* loc, bool transpose, const dom::Sequence<GLfloat>& value){
-        UniformMatrix3x4fv_base(loc, transpose, value.Length(), value.Elements());
+    template<typename T>
+    void UniformMatrix3x4fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
+        UniformMatrixAxBfv("uniformMatrix3x4fv", 3, 4, loc, transpose, FloatArr(arr));
     }
-    void UniformMatrix4x2fv(WebGLUniformLocation* loc, bool transpose, const dom::Sequence<GLfloat>& value){
-        UniformMatrix4x2fv_base(loc, transpose, value.Length(), value.Elements());
+    template<typename T>
+    void UniformMatrix4x2fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
+        UniformMatrixAxBfv("uniformMatrix4x2fv", 4, 2, loc, transpose, FloatArr(arr));
     }
-    void UniformMatrix4x3fv(WebGLUniformLocation* loc, bool transpose, const dom::Sequence<GLfloat>& value){
-        UniformMatrix4x3fv_base(loc, transpose, value.Length(), value.Elements());
+    template<typename T>
+    void UniformMatrix4x3fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
+        UniformMatrixAxBfv("uniformMatrix4x3fv", 4, 3, loc, transpose, FloatArr(arr));
     }
 
-    void UniformMatrix2x3fv(WebGLUniformLocation* loc, bool transpose, const dom::Float32Array& value){
-        value.ComputeLengthAndData();
-        UniformMatrix2x3fv_base(loc, transpose, value.Length(), value.Data());
-    }
-
-    void UniformMatrix2x4fv(WebGLUniformLocation* loc, bool transpose, const dom::Float32Array& value){
-        value.ComputeLengthAndData();
-        UniformMatrix2x4fv_base(loc, transpose, value.Length(), value.Data());
-    }
-
-    void UniformMatrix3x2fv(WebGLUniformLocation* loc, bool transpose, const dom::Float32Array& value){
-        value.ComputeLengthAndData();
-        UniformMatrix3x2fv_base(loc, transpose, value.Length(), value.Data());
-    }
-
-    void UniformMatrix3x4fv(WebGLUniformLocation* loc, bool transpose, const dom::Float32Array& value){
-        value.ComputeLengthAndData();
-        UniformMatrix3x4fv_base(loc, transpose, value.Length(), value.Data());
-    }
-
-    void UniformMatrix4x2fv(WebGLUniformLocation* loc, bool transpose, const dom::Float32Array& value){
-        value.ComputeLengthAndData();
-        UniformMatrix4x2fv_base(loc, transpose, value.Length(), value.Data());
-    }
-
-    void UniformMatrix4x3fv(WebGLUniformLocation* loc, bool transpose, const dom::Float32Array& value){
-        value.ComputeLengthAndData();
-        UniformMatrix4x3fv_base(loc, transpose, value.Length(), value.Data());
-    }
+    ////////////////
 
 private:
     void VertexAttribI4iv(GLuint index, size_t length, const GLint* v);
     void VertexAttribI4uiv(GLuint index, size_t length, const GLuint* v);
 
 public:
     // GL 3.0 & ES 3.0
     void VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w);
--- a/dom/canvas/WebGL2ContextUniforms.cpp
+++ b/dom/canvas/WebGL2ContextUniforms.cpp
@@ -6,16 +6,17 @@
 #include "WebGL2Context.h"
 
 #include "GLContext.h"
 #include "mozilla/dom/WebGL2RenderingContextBinding.h"
 #include "mozilla/RefPtr.h"
 #include "WebGLBuffer.h"
 #include "WebGLContext.h"
 #include "WebGLProgram.h"
+#include "WebGLUniformLocation.h"
 #include "WebGLVertexArray.h"
 #include "WebGLVertexAttribData.h"
 
 namespace mozilla {
 
 bool
 WebGL2Context::ValidateUniformMatrixTranspose(bool /*transpose*/, const char* /*info*/)
 {
@@ -23,230 +24,52 @@ WebGL2Context::ValidateUniformMatrixTran
 }
 
 // -------------------------------------------------------------------------
 // Uniforms
 
 void
 WebGL2Context::Uniform1ui(WebGLUniformLocation* loc, GLuint v0)
 {
-    GLuint rawLoc;
-    if (!ValidateUniformSetter(loc, 1, LOCAL_GL_UNSIGNED_INT, "uniform1ui", &rawLoc))
+    if (!ValidateUniformSetter(loc, 1, LOCAL_GL_UNSIGNED_INT, "uniform1ui"))
         return;
 
     MakeContextCurrent();
-    gl->fUniform1ui(rawLoc, v0);
+    gl->fUniform1ui(loc->mLoc, v0);
 }
 
 void
 WebGL2Context::Uniform2ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1)
 {
-    GLuint rawLoc;
-    if (!ValidateUniformSetter(loc, 2, LOCAL_GL_UNSIGNED_INT, "uniform2ui", &rawLoc))
+    if (!ValidateUniformSetter(loc, 2, LOCAL_GL_UNSIGNED_INT, "uniform2ui"))
         return;
 
     MakeContextCurrent();
-    gl->fUniform2ui(rawLoc, v0, v1);
+    gl->fUniform2ui(loc->mLoc, v0, v1);
 }
 
 void
 WebGL2Context::Uniform3ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2)
 {
-    GLuint rawLoc;
-    if (!ValidateUniformSetter(loc, 3, LOCAL_GL_UNSIGNED_INT, "uniform3ui", &rawLoc))
-        return;
-
-    MakeContextCurrent();
-    gl->fUniform3ui(rawLoc, v0, v1, v2);
-}
-
-void
-WebGL2Context::Uniform4ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
-{
-    GLuint rawLoc;
-    if (!ValidateUniformSetter(loc, 4, LOCAL_GL_UNSIGNED_INT, "uniform4ui", &rawLoc))
+    if (!ValidateUniformSetter(loc, 3, LOCAL_GL_UNSIGNED_INT, "uniform3ui"))
         return;
 
     MakeContextCurrent();
-    gl->fUniform4ui(rawLoc, v0, v1, v2, v3);
-}
-
-void
-WebGL2Context::Uniform1uiv_base(WebGLUniformLocation* loc, size_t arrayLength,
-                                const GLuint* data)
-{
-    GLuint rawLoc;
-    GLsizei numElementsToUpload;
-
-    if (!ValidateUniformArraySetter(loc, 1, LOCAL_GL_UNSIGNED_INT, arrayLength,
-                                    "uniform1uiv", &rawLoc, &numElementsToUpload))
-    {
-        return;
-    }
-
-    MakeContextCurrent();
-    gl->fUniform1uiv(rawLoc, numElementsToUpload, data);
-}
-
-void
-WebGL2Context::Uniform2uiv_base(WebGLUniformLocation* loc, size_t arrayLength,
-                                const GLuint* data)
-{
-    GLuint rawLoc;
-    GLsizei numElementsToUpload;
-
-    if (!ValidateUniformArraySetter(loc, 2, LOCAL_GL_UNSIGNED_INT, arrayLength,
-                                    "uniform2uiv", &rawLoc, &numElementsToUpload))
-    {
-        return;
-    }
-
-    MakeContextCurrent();
-    gl->fUniform2uiv(rawLoc, numElementsToUpload, data);
-}
-
-void
-WebGL2Context::Uniform3uiv_base(WebGLUniformLocation* loc, size_t arrayLength,
-                                const GLuint* data)
-{
-    GLuint rawLoc;
-    GLsizei numElementsToUpload;
-
-    if (!ValidateUniformArraySetter(loc, 3, LOCAL_GL_UNSIGNED_INT, arrayLength,
-                                    "uniform3uiv", &rawLoc, &numElementsToUpload))
-    {
-        return;
-    }
-
-    MakeContextCurrent();
-    gl->fUniform1uiv(rawLoc, numElementsToUpload, data);
-}
-
-void
-WebGL2Context::Uniform4uiv_base(WebGLUniformLocation* loc, size_t arrayLength,
-                                const GLuint* data)
-{
-    GLuint rawLoc;
-    GLsizei numElementsToUpload;
-
-    if (!ValidateUniformArraySetter(loc, 4, LOCAL_GL_UNSIGNED_INT, arrayLength,
-                                    "uniform4uiv", &rawLoc, &numElementsToUpload)) {
-        return;
-    }
-
-    MakeContextCurrent();
-    gl->fUniform4uiv(rawLoc, numElementsToUpload, data);
+    gl->fUniform3ui(loc->mLoc, v0, v1, v2);
 }
 
 void
-WebGL2Context::UniformMatrix2x3fv_base(WebGLUniformLocation* loc, bool transpose,
-                                       size_t arrayLength, const GLfloat* data)
-{
-    GLuint rawLoc;
-    GLsizei numElementsToUpload;
-
-    if (!ValidateUniformMatrixArraySetter(loc, 2, 3, LOCAL_GL_FLOAT, arrayLength,
-                                          transpose, "uniformMatrix2x3fv",
-                                          &rawLoc, &numElementsToUpload))
-    {
-        return;
-    }
-
-    MakeContextCurrent();
-    gl->fUniformMatrix2x3fv(rawLoc, numElementsToUpload, transpose, data);
-}
-
-void
-WebGL2Context::UniformMatrix2x4fv_base(WebGLUniformLocation* loc, bool transpose,
-                                       size_t arrayLength, const GLfloat* data)
+WebGL2Context::Uniform4ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2,
+                          GLuint v3)
 {
-    GLuint rawLoc;
-    GLsizei numElementsToUpload;
-
-    if (!ValidateUniformMatrixArraySetter(loc, 2, 4, LOCAL_GL_FLOAT, arrayLength,
-                                          transpose, "uniformMatrix2x4fv",
-                                          &rawLoc, &numElementsToUpload))
-    {
+    if (!ValidateUniformSetter(loc, 4, LOCAL_GL_UNSIGNED_INT, "uniform4ui"))
         return;
-    }
-
-    MakeContextCurrent();
-    gl->fUniformMatrix2x4fv(rawLoc, numElementsToUpload, transpose, data);
-}
-
-void
-WebGL2Context::UniformMatrix3x2fv_base(WebGLUniformLocation* loc, bool transpose,
-                                       size_t arrayLength, const GLfloat* data)
-{
-    GLuint rawLoc;
-    GLsizei numElementsToUpload;
-
-    if (!ValidateUniformMatrixArraySetter(loc, 3, 2, LOCAL_GL_FLOAT, arrayLength,
-                                          transpose, "uniformMatrix3x2fv",
-                                          &rawLoc, &numElementsToUpload))
-    {
-        return;
-    }
 
     MakeContextCurrent();
-    gl->fUniformMatrix3x2fv(rawLoc, numElementsToUpload, transpose, data);
-}
-
-void
-WebGL2Context::UniformMatrix3x4fv_base(WebGLUniformLocation* loc, bool transpose,
-                                       size_t arrayLength, const GLfloat* data)
-{
-    GLuint rawLoc;
-    GLsizei numElementsToUpload;
-
-    if (!ValidateUniformMatrixArraySetter(loc, 3, 4, LOCAL_GL_FLOAT, arrayLength,
-                                          transpose, "uniformMatrix3x4fv",
-                                          &rawLoc, &numElementsToUpload))
-    {
-        return;
-    }
-
-    MakeContextCurrent();
-    gl->fUniformMatrix3x4fv(rawLoc, numElementsToUpload, transpose, data);
-}
-
-void
-WebGL2Context::UniformMatrix4x2fv_base(WebGLUniformLocation* loc, bool transpose,
-                                       size_t arrayLength, const GLfloat* data)
-{
-    GLuint rawLoc;
-    GLsizei numElementsToUpload;
-
-    if (!ValidateUniformMatrixArraySetter(loc, 4, 2, LOCAL_GL_FLOAT, arrayLength,
-                                          transpose, "uniformMatrix4x2fv",
-                                          &rawLoc, &numElementsToUpload))
-    {
-        return;
-    }
-
-    MakeContextCurrent();
-    gl->fUniformMatrix4x2fv(rawLoc, numElementsToUpload, transpose, data);
-}
-
-void
-WebGL2Context::UniformMatrix4x3fv_base(WebGLUniformLocation* loc, bool transpose,
-                                       size_t arrayLength, const GLfloat* data)
-{
-    GLuint rawLoc;
-    GLsizei numElementsToUpload;
-
-    if (!ValidateUniformMatrixArraySetter(loc, 4, 3, LOCAL_GL_FLOAT, arrayLength,
-                                          transpose, "uniformMatrix4x3fv",
-                                          &rawLoc, &numElementsToUpload))
-    {
-        return;
-    }
-
-    MakeContextCurrent();
-    gl->fUniformMatrix4x3fv(rawLoc, numElementsToUpload, transpose, data);
+    gl->fUniform4ui(loc->mLoc, v0, v1, v2, v3);
 }
 
 
 // -------------------------------------------------------------------------
 // Uniform Buffer Objects and Transform Feedback Buffers
 // TODO(djg): Implemented in WebGLContext
 /*
     void BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer);
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -561,193 +561,138 @@ public:
     void StencilFunc(GLenum func, GLint ref, GLuint mask);
     void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
     void StencilMask(GLuint mask);
     void StencilMaskSeparate(GLenum face, GLuint mask);
     void StencilOp(GLenum sfail, GLenum dpfail, GLenum dppass);
     void StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail,
                            GLenum dppass);
 
+    //////
+
     void Uniform1i(WebGLUniformLocation* loc, GLint x);
     void Uniform2i(WebGLUniformLocation* loc, GLint x, GLint y);
     void Uniform3i(WebGLUniformLocation* loc, GLint x, GLint y, GLint z);
-    void Uniform4i(WebGLUniformLocation* loc, GLint x, GLint y, GLint z,
-                   GLint w);
+    void Uniform4i(WebGLUniformLocation* loc, GLint x, GLint y, GLint z, GLint w);
 
     void Uniform1f(WebGLUniformLocation* loc, GLfloat x);
     void Uniform2f(WebGLUniformLocation* loc, GLfloat x, GLfloat y);
     void Uniform3f(WebGLUniformLocation* loc, GLfloat x, GLfloat y, GLfloat z);
-    void Uniform4f(WebGLUniformLocation* loc, GLfloat x, GLfloat y, GLfloat z,
-                   GLfloat w);
+    void Uniform4f(WebGLUniformLocation* loc, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+
+    //////////////////////////
+
+protected:
+    template<typename elemT, typename arrT>
+    struct Arr {
+        size_t dataCount;
+        const elemT* data;
 
-    // Int array
-    void Uniform1iv(WebGLUniformLocation* loc, const dom::Int32Array& arr) {
-        arr.ComputeLengthAndData();
-        Uniform1iv_base(loc, arr.Length(), arr.Data());
-    }
-    void Uniform1iv(WebGLUniformLocation* loc,
-                    const dom::Sequence<GLint>& arr)
-    {
-        Uniform1iv_base(loc, arr.Length(), arr.Elements());
-    }
-    void Uniform1iv_base(WebGLUniformLocation* loc, size_t arrayLength,
-                         const GLint* data);
+        explicit Arr(const arrT& arr) {
+            arr.ComputeLengthAndData();
+            dataCount = arr.Length();
+            data = arr.Data();
+        }
 
-    void Uniform2iv(WebGLUniformLocation* loc, const dom::Int32Array& arr) {
-        arr.ComputeLengthAndData();
-        Uniform2iv_base(loc, arr.Length(), arr.Data());
-    }
-    void Uniform2iv(WebGLUniformLocation* loc,
-                    const dom::Sequence<GLint>& arr)
-    {
-        Uniform2iv_base(loc, arr.Length(), arr.Elements());
-    }
-    void Uniform2iv_base(WebGLUniformLocation* loc, size_t arrayLength,
-                         const GLint* data);
+        explicit Arr(const dom::Sequence<elemT>& arr) {
+            dataCount = arr.Length();
+            data = arr.Elements();
+        }
+    };
 
-    void Uniform3iv(WebGLUniformLocation* loc, const dom::Int32Array& arr) {
-        arr.ComputeLengthAndData();
-        Uniform3iv_base(loc, arr.Length(), arr.Data());
-    }
-    void Uniform3iv(WebGLUniformLocation* loc,
-                    const dom::Sequence<GLint>& arr)
-    {
-        Uniform3iv_base(loc, arr.Length(), arr.Elements());
-    }
-    void Uniform3iv_base(WebGLUniformLocation* loc, size_t arrayLength,
-                         const GLint* data);
+    typedef Arr<GLint, dom::Int32Array> IntArr;
+    typedef Arr<GLfloat, dom::Float32Array> FloatArr;
+
+    ////////////////
+
+    void UniformNiv(const char* funcName, uint8_t N, WebGLUniformLocation* loc,
+                    const IntArr& arr);
+
+    void UniformNfv(const char* funcName, uint8_t N, WebGLUniformLocation* loc,
+                    const FloatArr& arr);
 
-    void Uniform4iv(WebGLUniformLocation* loc, const dom::Int32Array& arr) {
-        arr.ComputeLengthAndData();
-        Uniform4iv_base(loc, arr.Length(), arr.Data());
-    }
-    void Uniform4iv(WebGLUniformLocation* loc,
-                    const dom::Sequence<GLint>& arr)
-    {
-        Uniform4iv_base(loc, arr.Length(), arr.Elements());
-    }
-    void Uniform4iv_base(WebGLUniformLocation* loc, size_t arrayLength,
-                         const GLint* data);
+    void UniformMatrixAxBfv(const char* funcName, uint8_t A, uint8_t B,
+                            WebGLUniformLocation* loc, bool transpose,
+                            const FloatArr& arr);
 
-    // Float array
-    void Uniform1fv(WebGLUniformLocation* loc, const dom::Float32Array& arr) {
-        arr.ComputeLengthAndData();
-        Uniform1fv_base(loc, arr.Length(), arr.Data());
-    }
-    void Uniform1fv(WebGLUniformLocation* loc,
-                    const dom::Sequence<GLfloat>& arr)
-    {
-        Uniform1fv_base(loc, arr.Length(), arr.Elements());
-    }
-    void Uniform1fv_base(WebGLUniformLocation* loc, size_t arrayLength,
-                         const GLfloat* data);
+    ////////////////
 
-    void Uniform2fv(WebGLUniformLocation* loc, const dom::Float32Array& arr) {
-        arr.ComputeLengthAndData();
-        Uniform2fv_base(loc, arr.Length(), arr.Data());
+public:
+    template<typename T>
+    void Uniform1iv(WebGLUniformLocation* loc, const T& arr) {
+        UniformNiv("uniform1iv", 1, loc, IntArr(arr));
     }
-    void Uniform2fv(WebGLUniformLocation* loc,
-                    const dom::Sequence<GLfloat>& arr)
-    {
-        Uniform2fv_base(loc, arr.Length(), arr.Elements());
-    }
-    void Uniform2fv_base(WebGLUniformLocation* loc, size_t arrayLength,
-                         const GLfloat* data);
-
-    void Uniform3fv(WebGLUniformLocation* loc, const dom::Float32Array& arr) {
-        arr.ComputeLengthAndData();
-        Uniform3fv_base(loc, arr.Length(), arr.Data());
+    template<typename T>
+    void Uniform2iv(WebGLUniformLocation* loc, const T& arr) {
+        UniformNiv("uniform2iv", 2, loc, IntArr(arr));
     }
-    void Uniform3fv(WebGLUniformLocation* loc,
-                    const dom::Sequence<GLfloat>& arr)
-    {
-        Uniform3fv_base(loc, arr.Length(), arr.Elements());
+    template<typename T>
+    void Uniform3iv(WebGLUniformLocation* loc, const T& arr) {
+        UniformNiv("uniform3iv", 3, loc, IntArr(arr));
     }
-    void Uniform3fv_base(WebGLUniformLocation* loc, size_t arrayLength,
-                         const GLfloat* data);
+    template<typename T>
+    void Uniform4iv(WebGLUniformLocation* loc, const T& arr) {
+        UniformNiv("uniform4iv", 4, loc, IntArr(arr));
+    }
 
-    void Uniform4fv(WebGLUniformLocation* loc, const dom::Float32Array& arr) {
-        arr.ComputeLengthAndData();
-        Uniform4fv_base(loc, arr.Length(), arr.Data());
-    }
-    void Uniform4fv(WebGLUniformLocation* loc,
-                    const dom::Sequence<GLfloat>& arr)
-    {
-        Uniform4fv_base(loc, arr.Length(), arr.Elements());
-    }
-    void Uniform4fv_base(WebGLUniformLocation* loc, size_t arrayLength,
-                         const GLfloat* data);
+    //////
 
-    // Matrix
-    void UniformMatrix2fv(WebGLUniformLocation* loc, WebGLboolean transpose,
-                          const dom::Float32Array& value)
-    {
-        value.ComputeLengthAndData();
-        UniformMatrix2fv_base(loc, transpose, value.Length(), value.Data());
+    template<typename T>
+    void Uniform1fv(WebGLUniformLocation* loc, const T& arr) {
+        UniformNfv("uniform1fv", 1, loc, FloatArr(arr));
+    }
+    template<typename T>
+    void Uniform2fv(WebGLUniformLocation* loc, const T& arr) {
+        UniformNfv("uniform2fv", 2, loc, FloatArr(arr));
     }
-    void UniformMatrix2fv(WebGLUniformLocation* loc, WebGLboolean transpose,
-                          const dom::Sequence<float>& value)
-    {
-        UniformMatrix2fv_base(loc, transpose, value.Length(),
-                              value.Elements());
+    template<typename T>
+    void Uniform3fv(WebGLUniformLocation* loc, const T& arr) {
+        UniformNfv("uniform3fv", 3, loc, FloatArr(arr));
     }
-    void UniformMatrix2fv_base(WebGLUniformLocation* loc, bool transpose,
-                               size_t arrayLength, const float* data);
-
-    void UniformMatrix3fv(WebGLUniformLocation* loc, WebGLboolean transpose,
-                          const dom::Float32Array& value)
-    {
-        value.ComputeLengthAndData();
-        UniformMatrix3fv_base(loc, transpose, value.Length(), value.Data());
+    template<typename T>
+    void Uniform4fv(WebGLUniformLocation* loc, const T& arr) {
+        UniformNfv("uniform4fv", 4, loc, FloatArr(arr));
     }
-    void UniformMatrix3fv(WebGLUniformLocation* loc, WebGLboolean transpose,
-                          const dom::Sequence<float>& value)
-    {
-        UniformMatrix3fv_base(loc, transpose, value.Length(), value.Elements());
-    }
-    void UniformMatrix3fv_base(WebGLUniformLocation* loc, bool transpose,
-                               size_t arrayLength, const float* data);
+
+    //////
 
-    void UniformMatrix4fv(WebGLUniformLocation* loc, WebGLboolean transpose,
-                          const dom::Float32Array& value)
-    {
-        value.ComputeLengthAndData();
-        UniformMatrix4fv_base(loc, transpose, value.Length(), value.Data());
+    template<typename T>
+    void UniformMatrix2fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
+        UniformMatrixAxBfv("uniformMatrix2fv", 2, 2, loc, transpose, FloatArr(arr));
     }
-    void UniformMatrix4fv(WebGLUniformLocation* loc, bool transpose,
-                          const dom::Sequence<float>& value)
-    {
-        UniformMatrix4fv_base(loc, transpose, value.Length(),
-                              value.Elements());
+    template<typename T>
+    void UniformMatrix3fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
+        UniformMatrixAxBfv("uniformMatrix3fv", 3, 3, loc, transpose, FloatArr(arr));
     }
-    void UniformMatrix4fv_base(WebGLUniformLocation* loc, bool transpose,
-                               size_t arrayLength, const float* data);
+    template<typename T>
+    void UniformMatrix4fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
+        UniformMatrixAxBfv("uniformMatrix4fv", 4, 4, loc, transpose, FloatArr(arr));
+    }
+
+    ////////////////////////////////////
 
     void UseProgram(WebGLProgram* prog);
 
     bool ValidateAttribArraySetter(const char* name, uint32_t count,
                                    uint32_t arrayLength);
     bool ValidateUniformLocation(WebGLUniformLocation* loc, const char* funcName);
     bool ValidateUniformSetter(WebGLUniformLocation* loc, uint8_t setterSize,
-                               GLenum setterType, const char* info,
-                               GLuint* out_rawLoc);
+                               GLenum setterType, const char* funcName);
     bool ValidateUniformArraySetter(WebGLUniformLocation* loc,
                                     uint8_t setterElemSize, GLenum setterType,
-                                    size_t setterArraySize, const char* info,
-                                    GLuint* out_rawLoc,
-                                    GLsizei* out_numElementsToUpload);
+                                    uint32_t setterArraySize, const char* funcName,
+                                    uint32_t* out_numElementsToUpload);
     bool ValidateUniformMatrixArraySetter(WebGLUniformLocation* loc,
                                           uint8_t setterCols,
                                           uint8_t setterRows,
                                           GLenum setterType,
-                                          size_t setterArraySize,
+                                          uint32_t setterArraySize,
                                           bool setterTranspose,
-                                          const char* info,
-                                          GLuint* out_rawLoc,
-                                          GLsizei* out_numElementsToUpload);
+                                          const char* funcName,
+                                          uint32_t* out_numElementsToUpload);
     void ValidateProgram(WebGLProgram* prog);
     bool ValidateUniformLocation(const char* info, WebGLUniformLocation* loc);
     bool ValidateSamplerUniformSetter(const char* info,
                                       WebGLUniformLocation* loc, GLint value);
     void Viewport(GLint x, GLint y, GLsizei width, GLsizei height);
 // -----------------------------------------------------------------------------
 // WEBGL_lose_context
 public:
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebGLContext.h"
+#include "WebGL2Context.h"
 
 #include "WebGLActiveInfo.h"
 #include "WebGLContextUtils.h"
 #include "WebGLBuffer.h"
 #include "WebGLVertexAttribData.h"
 #include "WebGLShader.h"
 #include "WebGLProgram.h"
 #include "WebGLUniformLocation.h"
@@ -1842,326 +1843,278 @@ WebGLContext::StencilOpSeparate(GLenum f
 
     MakeContextCurrent();
     gl->fStencilOpSeparate(face, sfail, dpfail, dppass);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Uniform setters.
 
+class ValidateIfSampler
+{
+    const WebGLUniformLocation* const mLoc;
+    const size_t mDataCount;
+    const GLint* const mData;
+    bool mIsValidatedSampler;
+
+public:
+    ValidateIfSampler(WebGLContext* webgl, const char* funcName,
+                      WebGLUniformLocation* loc, size_t dataCount, const GLint* data,
+                      bool* const out_error)
+        : mLoc(loc)
+        , mDataCount(dataCount)
+        , mData(data)
+        , mIsValidatedSampler(false)
+    {
+        if (!mLoc->mInfo->mSamplerTexList) {
+            *out_error = false;
+            return;
+        }
+
+        for (size_t i = 0; i < mDataCount; i++) {
+            const auto& val = mData[i];
+            if (val < 0 || uint32_t(val) >= webgl->GLMaxTextureUnits()) {
+                webgl->ErrorInvalidValue("%s: This uniform location is a sampler, but %d"
+                                         " is not a valid texture unit.",
+                                         funcName, val);
+                *out_error = true;
+                return;
+            }
+        }
+
+        mIsValidatedSampler = true;
+        *out_error = false;
+    }
+
+    ~ValidateIfSampler() {
+        if (!mIsValidatedSampler)
+            return;
+
+        auto& samplerValues = mLoc->mInfo->mSamplerValues;
+
+        for (size_t i = 0; i < mDataCount; i++) {
+            const size_t curIndex = mLoc->mArrayIndex + i;
+            if (curIndex >= samplerValues.size())
+                break;
+
+            samplerValues[curIndex] = mData[i];
+        }
+    }
+};
+
+////////////////////
+
 void
 WebGLContext::Uniform1i(WebGLUniformLocation* loc, GLint a1)
 {
-    GLuint rawLoc;
-    if (!ValidateUniformSetter(loc, 1, LOCAL_GL_INT, "uniform1i", &rawLoc))
+    const char funcName[] = "uniform1i";
+    if (!ValidateUniformSetter(loc, 1, LOCAL_GL_INT, funcName))
         return;
 
-    // Only uniform1i can take sampler settings.
-    if (!loc->ValidateSamplerSetter(a1, this, "uniform1i"))
+    bool error;
+    const ValidateIfSampler validate(this, funcName, loc, 1, &a1, &error);
+    if (error)
         return;
 
     MakeContextCurrent();
-    gl->fUniform1i(rawLoc, a1);
+    gl->fUniform1i(loc->mLoc, a1);
 }
 
 void
 WebGLContext::Uniform2i(WebGLUniformLocation* loc, GLint a1, GLint a2)
 {
-    GLuint rawLoc;
-    if (!ValidateUniformSetter(loc, 2, LOCAL_GL_INT, "uniform2i", &rawLoc))
+    const char funcName[] = "uniform2i";
+    if (!ValidateUniformSetter(loc, 2, LOCAL_GL_INT, funcName))
         return;
 
     MakeContextCurrent();
-    gl->fUniform2i(rawLoc, a1, a2);
+    gl->fUniform2i(loc->mLoc, a1, a2);
 }
 
 void
 WebGLContext::Uniform3i(WebGLUniformLocation* loc, GLint a1, GLint a2, GLint a3)
 {
-    GLuint rawLoc;
-    if (!ValidateUniformSetter(loc, 3, LOCAL_GL_INT, "uniform3i", &rawLoc))
+    const char funcName[] = "uniform3i";
+    if (!ValidateUniformSetter(loc, 3, LOCAL_GL_INT, funcName))
         return;
 
     MakeContextCurrent();
-    gl->fUniform3i(rawLoc, a1, a2, a3);
+    gl->fUniform3i(loc->mLoc, a1, a2, a3);
 }
 
 void
 WebGLContext::Uniform4i(WebGLUniformLocation* loc, GLint a1, GLint a2, GLint a3,
                         GLint a4)
 {
-    GLuint rawLoc;
-    if (!ValidateUniformSetter(loc, 4, LOCAL_GL_INT, "uniform4i", &rawLoc))
+    const char funcName[] = "uniform4i";
+    if (!ValidateUniformSetter(loc, 4, LOCAL_GL_INT, funcName))
         return;
 
     MakeContextCurrent();
-    gl->fUniform4i(rawLoc, a1, a2, a3, a4);
+    gl->fUniform4i(loc->mLoc, a1, a2, a3, a4);
 }
 
+//////////
+
 void
 WebGLContext::Uniform1f(WebGLUniformLocation* loc, GLfloat a1)
 {
-    GLuint rawLoc;
-    if (!ValidateUniformSetter(loc, 1, LOCAL_GL_FLOAT, "uniform1f", &rawLoc))
+    const char funcName[] = "uniform1f";
+    if (!ValidateUniformSetter(loc, 1, LOCAL_GL_FLOAT, funcName))
         return;
 
     MakeContextCurrent();
-    gl->fUniform1f(rawLoc, a1);
+    gl->fUniform1f(loc->mLoc, a1);
 }
 
 void
 WebGLContext::Uniform2f(WebGLUniformLocation* loc, GLfloat a1, GLfloat a2)
 {
-    GLuint rawLoc;
-    if (!ValidateUniformSetter(loc, 2, LOCAL_GL_FLOAT, "uniform2f", &rawLoc))
+    const char funcName[] = "uniform2f";
+    if (!ValidateUniformSetter(loc, 2, LOCAL_GL_FLOAT, funcName))
         return;
 
     MakeContextCurrent();
-    gl->fUniform2f(rawLoc, a1, a2);
+    gl->fUniform2f(loc->mLoc, a1, a2);
 }
 
 void
 WebGLContext::Uniform3f(WebGLUniformLocation* loc, GLfloat a1, GLfloat a2,
                         GLfloat a3)
 {
-    GLuint rawLoc;
-    if (!ValidateUniformSetter(loc, 3, LOCAL_GL_FLOAT, "uniform3f", &rawLoc))
+    const char funcName[] = "uniform3f";
+    if (!ValidateUniformSetter(loc, 3, LOCAL_GL_FLOAT, funcName))
         return;
 
     MakeContextCurrent();
-    gl->fUniform3f(rawLoc, a1, a2, a3);
+    gl->fUniform3f(loc->mLoc, a1, a2, a3);
 }
 
 void
 WebGLContext::Uniform4f(WebGLUniformLocation* loc, GLfloat a1, GLfloat a2,
                         GLfloat a3, GLfloat a4)
 {
-    GLuint rawLoc;
-    if (!ValidateUniformSetter(loc, 4, LOCAL_GL_FLOAT, "uniform4f", &rawLoc))
+    const char funcName[] = "uniform4f";
+    if (!ValidateUniformSetter(loc, 4, LOCAL_GL_FLOAT, funcName))
         return;
 
     MakeContextCurrent();
-    gl->fUniform4f(rawLoc, a1, a2, a3, a4);
+    gl->fUniform4f(loc->mLoc, a1, a2, a3, a4);
 }
 
 ////////////////////////////////////////
 // Array
 
 void
-WebGLContext::Uniform1iv_base(WebGLUniformLocation* loc, size_t arrayLength,
-                              const GLint* data)
-{
-    GLuint rawLoc;
-    GLsizei numElementsToUpload;
-    if (!ValidateUniformArraySetter(loc, 1, LOCAL_GL_INT, arrayLength,
-                                    "uniform1iv", &rawLoc,
-                                    &numElementsToUpload))
-    {
-        return;
-    }
-
-    if (!loc->ValidateSamplerSetter(data[0], this, "uniform1iv"))
-        return;
-
-    MakeContextCurrent();
-    gl->fUniform1iv(rawLoc, numElementsToUpload, data);
-}
-
-void
-WebGLContext::Uniform2iv_base(WebGLUniformLocation* loc, size_t arrayLength,
-                              const GLint* data)
-{
-    GLuint rawLoc;
-    GLsizei numElementsToUpload;
-    if (!ValidateUniformArraySetter(loc, 2, LOCAL_GL_INT, arrayLength,
-                                    "uniform2iv", &rawLoc,
-                                    &numElementsToUpload))
-    {
-        return;
-    }
-
-    if (!loc->ValidateSamplerSetter(data[0], this, "uniform2iv") ||
-        !loc->ValidateSamplerSetter(data[1], this, "uniform2iv"))
-    {
-        return;
-    }
-
-    MakeContextCurrent();
-    gl->fUniform2iv(rawLoc, numElementsToUpload, data);
-}
-
-void
-WebGLContext::Uniform3iv_base(WebGLUniformLocation* loc, size_t arrayLength,
-                              const GLint* data)
+WebGLContext::UniformNiv(const char* funcName, uint8_t N, WebGLUniformLocation* loc,
+                         const IntArr& arr)
 {
-    GLuint rawLoc;
-    GLsizei numElementsToUpload;
-    if (!ValidateUniformArraySetter(loc, 3, LOCAL_GL_INT, arrayLength,
-                                    "uniform3iv", &rawLoc,
-                                    &numElementsToUpload))
-    {
-        return;
-    }
-
-    if (!loc->ValidateSamplerSetter(data[0], this, "uniform3iv") ||
-        !loc->ValidateSamplerSetter(data[1], this, "uniform3iv") ||
-        !loc->ValidateSamplerSetter(data[2], this, "uniform3iv"))
-    {
-        return;
-    }
-
-    MakeContextCurrent();
-    gl->fUniform3iv(rawLoc, numElementsToUpload, data);
-}
-
-void
-WebGLContext::Uniform4iv_base(WebGLUniformLocation* loc, size_t arrayLength,
-                              const GLint* data)
-{
-    GLuint rawLoc;
-    GLsizei numElementsToUpload;
-    if (!ValidateUniformArraySetter(loc, 4, LOCAL_GL_INT, arrayLength,
-                                    "uniform4iv", &rawLoc,
-                                    &numElementsToUpload))
-    {
-        return;
-    }
-
-    if (!loc->ValidateSamplerSetter(data[0], this, "uniform4iv") ||
-        !loc->ValidateSamplerSetter(data[1], this, "uniform4iv") ||
-        !loc->ValidateSamplerSetter(data[2], this, "uniform4iv") ||
-        !loc->ValidateSamplerSetter(data[3], this, "uniform4iv"))
-    {
-        return;
-    }
-
-    MakeContextCurrent();
-    gl->fUniform4iv(rawLoc, numElementsToUpload, data);
-}
-
-void
-WebGLContext::Uniform1fv_base(WebGLUniformLocation* loc, size_t arrayLength,
-                              const GLfloat* data)
-{
-    GLuint rawLoc;
-    GLsizei numElementsToUpload;
-    if (!ValidateUniformArraySetter(loc, 1, LOCAL_GL_FLOAT, arrayLength,
-                                    "uniform1fv", &rawLoc,
+    uint32_t numElementsToUpload;
+    if (!ValidateUniformArraySetter(loc, N, LOCAL_GL_INT, arr.dataCount, funcName,
                                     &numElementsToUpload))
     {
         return;
     }
 
-    MakeContextCurrent();
-    gl->fUniform1fv(rawLoc, numElementsToUpload, data);
-}
-
-void
-WebGLContext::Uniform2fv_base(WebGLUniformLocation* loc, size_t arrayLength,
-                              const GLfloat* data)
-{
-    GLuint rawLoc;
-    GLsizei numElementsToUpload;
-    if (!ValidateUniformArraySetter(loc, 2, LOCAL_GL_FLOAT, arrayLength,
-                                    "uniform2fv", &rawLoc,
-                                    &numElementsToUpload))
-    {
+    bool error;
+    const ValidateIfSampler samplerValidator(this, funcName, loc, numElementsToUpload,
+                                             arr.data, &error);
+    if (error)
         return;
-    }
+
+    static const decltype(&gl::GLContext::fUniform1iv) kFuncList[] = {
+        &gl::GLContext::fUniform1iv,
+        &gl::GLContext::fUniform2iv,
+        &gl::GLContext::fUniform3iv,
+        &gl::GLContext::fUniform4iv
+    };
+    const auto func = kFuncList[N-1];
 
     MakeContextCurrent();
-    gl->fUniform2fv(rawLoc, numElementsToUpload, data);
+    (gl->*func)(loc->mLoc, numElementsToUpload, arr.data);
 }
 
 void
-WebGLContext::Uniform3fv_base(WebGLUniformLocation* loc, size_t arrayLength,
-                              const GLfloat* data)
+WebGL2Context::UniformNuiv(const char* funcName, uint8_t N, WebGLUniformLocation* loc,
+                           const UintArr& arr)
 {
-    GLuint rawLoc;
-    GLsizei numElementsToUpload;
-    if (!ValidateUniformArraySetter(loc, 3, LOCAL_GL_FLOAT, arrayLength,
-                                    "uniform3fv", &rawLoc,
-                                    &numElementsToUpload))
+    uint32_t numElementsToUpload;
+    if (!ValidateUniformArraySetter(loc, N, LOCAL_GL_UNSIGNED_INT, arr.dataCount,
+                                    funcName, &numElementsToUpload))
     {
         return;
     }
+    MOZ_ASSERT(!loc->mInfo->mSamplerTexList, "Should not be a sampler.");
+
+    static const decltype(&gl::GLContext::fUniform1uiv) kFuncList[] = {
+        &gl::GLContext::fUniform1uiv,
+        &gl::GLContext::fUniform2uiv,
+        &gl::GLContext::fUniform3uiv,
+        &gl::GLContext::fUniform4uiv
+    };
+    const auto func = kFuncList[N-1];
 
     MakeContextCurrent();
-    gl->fUniform3fv(rawLoc, numElementsToUpload, data);
+    (gl->*func)(loc->mLoc, numElementsToUpload, arr.data);
 }
 
 void
-WebGLContext::Uniform4fv_base(WebGLUniformLocation* loc, size_t arrayLength,
-                              const GLfloat* data)
+WebGLContext::UniformNfv(const char* funcName, uint8_t N, WebGLUniformLocation* loc,
+                         const FloatArr& arr)
 {
-    GLuint rawLoc;
-    GLsizei numElementsToUpload;
-    if (!ValidateUniformArraySetter(loc, 4, LOCAL_GL_FLOAT, arrayLength,
-                                    "uniform4fv", &rawLoc,
+    uint32_t numElementsToUpload;
+    if (!ValidateUniformArraySetter(loc, N, LOCAL_GL_FLOAT, arr.dataCount, funcName,
                                     &numElementsToUpload))
     {
         return;
     }
+    MOZ_ASSERT(!loc->mInfo->mSamplerTexList, "Should not be a sampler.");
+
+    static const decltype(&gl::GLContext::fUniform1fv) kFuncList[] = {
+        &gl::GLContext::fUniform1fv,
+        &gl::GLContext::fUniform2fv,
+        &gl::GLContext::fUniform3fv,
+        &gl::GLContext::fUniform4fv
+    };
+    const auto func = kFuncList[N-1];
 
     MakeContextCurrent();
-    gl->fUniform4fv(rawLoc, numElementsToUpload, data);
-}
-
-////////////////////////////////////////
-// Matrix
-
-void
-WebGLContext::UniformMatrix2fv_base(WebGLUniformLocation* loc, bool transpose,
-                                    size_t arrayLength, const float* data)
-{
-    GLuint rawLoc;
-    GLsizei numElementsToUpload;
-    if (!ValidateUniformMatrixArraySetter(loc, 2, 2, LOCAL_GL_FLOAT, arrayLength,
-                                          transpose, "uniformMatrix2fv",
-                                          &rawLoc, &numElementsToUpload))
-    {
-        return;
-    }
-
-    MakeContextCurrent();
-    gl->fUniformMatrix2fv(rawLoc, numElementsToUpload, false, data);
+    (gl->*func)(loc->mLoc, numElementsToUpload, arr.data);
 }
 
 void
-WebGLContext::UniformMatrix3fv_base(WebGLUniformLocation* loc, bool transpose,
-                                    size_t arrayLength, const float* data)
+WebGLContext::UniformMatrixAxBfv(const char* funcName, uint8_t A, uint8_t B,
+                                 WebGLUniformLocation* loc, bool transpose,
+                                 const FloatArr& arr)
 {
-    GLuint rawLoc;
-    GLsizei numElementsToUpload;
-    if (!ValidateUniformMatrixArraySetter(loc, 3, 3, LOCAL_GL_FLOAT, arrayLength,
-                                          transpose, "uniformMatrix3fv",
-                                          &rawLoc, &numElementsToUpload))
+    uint32_t numElementsToUpload;
+    if (!ValidateUniformMatrixArraySetter(loc, A, B, LOCAL_GL_FLOAT, arr.dataCount,
+                                          transpose, funcName, &numElementsToUpload))
     {
         return;
     }
+    MOZ_ASSERT(!loc->mInfo->mSamplerTexList, "Should not be a sampler.");
+
+    static const decltype(&gl::GLContext::fUniformMatrix2fv) kFuncList[] = {
+        &gl::GLContext::fUniformMatrix2fv,
+        &gl::GLContext::fUniformMatrix2x3fv,
+        &gl::GLContext::fUniformMatrix2x4fv,
+
+        &gl::GLContext::fUniformMatrix3x2fv,
+        &gl::GLContext::fUniformMatrix3fv,
+        &gl::GLContext::fUniformMatrix3x4fv,
+
+        &gl::GLContext::fUniformMatrix4x2fv,
+        &gl::GLContext::fUniformMatrix4x3fv,
+        &gl::GLContext::fUniformMatrix4fv
+    };
+    const auto func = kFuncList[3*(A-2) + (B-2)];
 
     MakeContextCurrent();
-    gl->fUniformMatrix3fv(rawLoc, numElementsToUpload, false, data);
-}
-
-void
-WebGLContext::UniformMatrix4fv_base(WebGLUniformLocation* loc, bool transpose,
-                                    size_t arrayLength, const float* data)
-{
-    GLuint rawLoc;
-    GLsizei numElementsToUpload;
-    if (!ValidateUniformMatrixArraySetter(loc, 4, 4, LOCAL_GL_FLOAT, arrayLength,
-                                          transpose, "uniformMatrix4fv",
-                                          &rawLoc, &numElementsToUpload))
-    {
-        return;
-    }
-
-    MakeContextCurrent();
-    gl->fUniformMatrix4fv(rawLoc, numElementsToUpload, false, data);
+    (gl->*func)(loc->mLoc, numElementsToUpload, false, arr.data);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
 void
 WebGLContext::UseProgram(WebGLProgram* prog)
 {
     if (IsContextLost())
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -432,17 +432,17 @@ WebGLContext::ValidateUniformLocation(We
     if (!ValidateObject(funcName, loc))
         return false;
 
     if (!mCurrentProgram) {
         ErrorInvalidOperation("%s: No program is currently bound.", funcName);
         return false;
     }
 
-    return loc->ValidateForProgram(mCurrentProgram, this, funcName);
+    return loc->ValidateForProgram(mCurrentProgram, funcName);
 }
 
 bool
 WebGLContext::ValidateAttribArraySetter(const char* name, uint32_t setterElemSize,
                                         uint32_t arrayLength)
 {
     if (IsContextLost())
         return false;
@@ -454,92 +454,92 @@ WebGLContext::ValidateAttribArraySetter(
     }
 
     return true;
 }
 
 bool
 WebGLContext::ValidateUniformSetter(WebGLUniformLocation* loc,
                                     uint8_t setterElemSize, GLenum setterType,
-                                    const char* funcName, GLuint* out_rawLoc)
+                                    const char* funcName)
 {
     if (IsContextLost())
         return false;
 
     if (!ValidateUniformLocation(loc, funcName))
         return false;
 
-    if (!loc->ValidateSizeAndType(setterElemSize, setterType, this, funcName))
+    if (!loc->ValidateSizeAndType(setterElemSize, setterType, funcName))
         return false;
 
-    *out_rawLoc = loc->mLoc;
     return true;
 }
 
 bool
 WebGLContext::ValidateUniformArraySetter(WebGLUniformLocation* loc,
                                          uint8_t setterElemSize,
                                          GLenum setterType,
-                                         size_t setterArraySize,
+                                         uint32_t setterArraySize,
                                          const char* funcName,
-                                         GLuint* const out_rawLoc,
-                                         GLsizei* const out_numElementsToUpload)
+                                         uint32_t* const out_numElementsToUpload)
 {
     if (IsContextLost())
         return false;
 
     if (!ValidateUniformLocation(loc, funcName))
         return false;
 
-    if (!loc->ValidateSizeAndType(setterElemSize, setterType, this, funcName))
+    if (!loc->ValidateSizeAndType(setterElemSize, setterType, funcName))
+        return false;
+
+    if (!loc->ValidateArrayLength(setterElemSize, setterArraySize, funcName))
         return false;
 
-    if (!loc->ValidateArrayLength(setterElemSize, setterArraySize, this, funcName))
-        return false;
+    const auto& elemCount = loc->mInfo->mActiveInfo->mElemCount;
+    MOZ_ASSERT(elemCount > loc->mArrayIndex);
+    const uint32_t uniformElemCount = elemCount - loc->mArrayIndex;
 
-    MOZ_ASSERT((size_t)loc->mActiveInfo->mElemCount > loc->mArrayIndex);
-    size_t uniformElemCount = loc->mActiveInfo->mElemCount - loc->mArrayIndex;
-    *out_rawLoc = loc->mLoc;
-    *out_numElementsToUpload = std::min(uniformElemCount, setterArraySize / setterElemSize);
+    *out_numElementsToUpload = std::min(uniformElemCount,
+                                        setterArraySize / setterElemSize);
     return true;
 }
 
 bool
 WebGLContext::ValidateUniformMatrixArraySetter(WebGLUniformLocation* loc,
                                                uint8_t setterCols,
                                                uint8_t setterRows,
                                                GLenum setterType,
-                                               size_t setterArraySize,
+                                               uint32_t setterArraySize,
                                                bool setterTranspose,
                                                const char* funcName,
-                                               GLuint* const out_rawLoc,
-                                               GLsizei* const out_numElementsToUpload)
+                                               uint32_t* const out_numElementsToUpload)
 {
-    uint8_t setterElemSize = setterCols * setterRows;
+    const uint8_t setterElemSize = setterCols * setterRows;
 
     if (IsContextLost())
         return false;
 
     if (!ValidateUniformLocation(loc, funcName))
         return false;
 
-    if (!loc->ValidateSizeAndType(setterElemSize, setterType, this, funcName))
+    if (!loc->ValidateSizeAndType(setterElemSize, setterType, funcName))
         return false;
 
-    if (!loc->ValidateArrayLength(setterElemSize, setterArraySize, this, funcName))
+    if (!loc->ValidateArrayLength(setterElemSize, setterArraySize, funcName))
         return false;
 
     if (!ValidateUniformMatrixTranspose(setterTranspose, funcName))
         return false;
 
-    MOZ_ASSERT((size_t)loc->mActiveInfo->mElemCount > loc->mArrayIndex);
-    size_t uniformElemCount = loc->mActiveInfo->mElemCount - loc->mArrayIndex;
-    *out_rawLoc = loc->mLoc;
-    *out_numElementsToUpload = std::min(uniformElemCount, setterArraySize / setterElemSize);
+    const auto& elemCount = loc->mInfo->mActiveInfo->mElemCount;
+    MOZ_ASSERT(elemCount > loc->mArrayIndex);
+    const uint32_t uniformElemCount = elemCount - loc->mArrayIndex;
 
+    *out_numElementsToUpload = std::min(uniformElemCount,
+                                        setterArraySize / setterElemSize);
     return true;
 }
 
 bool
 WebGLContext::ValidateAttribIndex(GLuint index, const char* info)
 {
     bool valid = (index < MaxVertexAttribs());