Bug 732233 - Explicitly enforce spec in uniform setters - r=jgilbert
authorBenoit Jacob <bjacob@mozilla.com>
Mon, 16 Apr 2012 15:56:12 -0400
changeset 91755 b56db6eab47c0192cfc80b3baf328e494c394354
parent 91754 686e5bcf747ba2fc7b5e4babb791114ac734c5e3
child 91756 e74b044c18b8301b489f71b1ec383c0d3f49c7e6
push id22475
push userbjacob@mozilla.com
push dateMon, 16 Apr 2012 19:56:33 +0000
treeherdermozilla-central@e74b044c18b8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert
bugs732233
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 732233 - Explicitly enforce spec in uniform setters - r=jgilbert
content/canvas/src/WebGLContext.h
content/canvas/src/WebGLContextGL.cpp
content/canvas/src/WebGLContextValidate.cpp
content/canvas/test/webgl/failing_tests_windows.txt
content/canvas/test/webgl/test_webgl_conformance_test_suite.html
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -65,16 +65,18 @@
 
 #include "CheckedInt.h"
 #include "nsDataHashtable.h"
 
 #ifdef XP_MACOSX
 #include "ForceDiscreteGPUHelperCGL.h"
 #endif
 
+#include "angle/ShaderLang.h"
+
 /* 
  * Minimum value constants defined in 6.2 State Tables of OpenGL ES - 2.0.25
  *   https://bugzilla.mozilla.org/show_bug.cgi?id=686732
  * 
  * Exceptions: some of the following values are set to higher values than in the spec because
  * the values in the spec are ridiculously low. They are explicitly marked below
 */
 #define MINVALUE_GL_MAX_TEXTURE_SIZE                  1024  // Different from the spec, which sets it to 64 on page 162
@@ -1653,16 +1655,56 @@ public:
     }
 };
 
 struct WebGLMappedIdentifier {
     nsCString original, mapped; // ASCII strings
     WebGLMappedIdentifier(const nsACString& o, const nsACString& m) : original(o), mapped(m) {}
 };
 
+struct WebGLUniformInfo {
+    PRUint32 arraySize;
+    bool isArray;
+    ShDataType type;
+
+    WebGLUniformInfo(PRUint32 s = 0, bool a = false, ShDataType t = SH_NONE)
+        : arraySize(s), isArray(a), type(t) {}
+
+    int ElementSize() const {
+        switch (type) {
+            case SH_INT:
+            case SH_FLOAT:
+            case SH_BOOL:
+            case SH_SAMPLER_2D:
+            case SH_SAMPLER_CUBE:
+                return 1;
+            case SH_INT_VEC2:
+            case SH_FLOAT_VEC2:
+            case SH_BOOL_VEC2:
+                return 2;
+            case SH_INT_VEC3:
+            case SH_FLOAT_VEC3:
+            case SH_BOOL_VEC3:
+                return 3;
+            case SH_INT_VEC4:
+            case SH_FLOAT_VEC4:
+            case SH_BOOL_VEC4:
+            case SH_FLOAT_MAT2:
+                return 4;
+            case SH_FLOAT_MAT3:
+                return 9;
+            case SH_FLOAT_MAT4:
+                return 16;
+            default:
+                NS_ABORT(); // should never get here
+                return 0;
+        }
+    }
+};
+
 class WebGLShader MOZ_FINAL
     : public nsIWebGLShader
     , public WebGLRefCountedObject<WebGLShader>
     , public WebGLContextBoundObject
 {
     friend class WebGLContext;
     friend class WebGLProgram;
 
@@ -1728,16 +1770,17 @@ protected:
     WebGLuint mGLName;
     WebGLenum mType;
     nsString mSource;
     nsCString mTranslationLog; // The translation log should contain only ASCII characters
     bool mNeedsTranslation;
     WebGLMonotonicHandle mMonotonicHandle;
     nsTArray<WebGLMappedIdentifier> mAttributes;
     nsTArray<WebGLMappedIdentifier> mUniforms;
+    nsTArray<WebGLUniformInfo> mUniformInfos;
     int mAttribMaxNameLength;
 };
 
 /** Takes an ASCII string like "foo[i]", turns it into "foo" and returns "[i]" in bracketPart
   * 
   * \param string input/output: the string to split, becomes the string without the bracket part
   * \param bracketPart output: gets the bracket part.
   * 
@@ -1760,17 +1803,18 @@ static bool SplitLastSquareBracket(nsACS
 
     bracketPart.Assign(s);
     *s = 0;
     string.EndWriting();
     string.SetLength(s - string_start);
     return true;
 }
 
-typedef nsDataHashtable<nsCStringHashKey, nsCString> CStringHash;
+typedef nsDataHashtable<nsCStringHashKey, nsCString> CStringMap;
+typedef nsDataHashtable<nsCStringHashKey, WebGLUniformInfo> CStringToUniformInfoMap;
 
 class WebGLProgram MOZ_FINAL
     : public nsIWebGLProgram
     , public WebGLRefCountedObject<WebGLProgram>
     , public WebGLContextBoundObject
 {
 public:
     WebGLProgram(WebGLContext *context)
@@ -1862,17 +1906,17 @@ public:
     bool IsAttribInUse(unsigned i) const { return mAttribsInUse[i]; }
 
     /* Maps identifier |name| to the mapped identifier |*mappedName|
      * Both are ASCII strings.
      */
     void MapIdentifier(const nsACString& name, nsCString *mappedName) {
         if (!mIdentifierMap) {
             // if the identifier map doesn't exist yet, build it now
-            mIdentifierMap = new CStringHash;
+            mIdentifierMap = new CStringMap;
             mIdentifierMap->Init();
             for (size_t i = 0; i < mAttachedShaders.Length(); i++) {
                 for (size_t j = 0; j < mAttachedShaders[i]->mAttributes.Length(); j++) {
                     const WebGLMappedIdentifier& attrib = mAttachedShaders[i]->mAttributes[j];
                     mIdentifierMap->Put(attrib.original, attrib.mapped);
                 }
                 for (size_t j = 0; j < mAttachedShaders[i]->mUniforms.Length(); j++) {
                     const WebGLMappedIdentifier& uniform = mAttachedShaders[i]->mUniforms[j];
@@ -1910,17 +1954,17 @@ public:
     }
 
     /* Un-maps mapped identifier |name| to the original identifier |*reverseMappedName|
      * Both are ASCII strings.
      */
     void ReverseMapIdentifier(const nsACString& name, nsCString *reverseMappedName) {
         if (!mIdentifierReverseMap) {
             // if the identifier reverse map doesn't exist yet, build it now
-            mIdentifierReverseMap = new CStringHash;
+            mIdentifierReverseMap = new CStringMap;
             mIdentifierReverseMap->Init();
             for (size_t i = 0; i < mAttachedShaders.Length(); i++) {
                 for (size_t j = 0; j < mAttachedShaders[i]->mAttributes.Length(); j++) {
                     const WebGLMappedIdentifier& attrib = mAttachedShaders[i]->mAttributes[j];
                     mIdentifierReverseMap->Put(attrib.mapped, attrib.original);
                 }
                 for (size_t j = 0; j < mAttachedShaders[i]->mUniforms.Length(); j++) {
                     const WebGLMappedIdentifier& uniform = mAttachedShaders[i]->mUniforms[j];
@@ -1952,31 +1996,70 @@ public:
             return;
 
         // not found? return name unchanged. This case happens e.g. on bad user input, or when
         // we're not using identifier mapping, or if we didn't store an identifier in the map because
         // e.g. its mapping is trivial (as happens for short identifiers)
         reverseMappedName->Assign(name);
     }
 
+    /* Returns the uniform array size (or 1 if the uniform is not an array) of
+     * the uniform with given mapped identifier.
+     *
+     * Note: the input string |name| is the mapped identifier, not the original identifier.
+     */
+    WebGLUniformInfo GetUniformInfoForMappedIdentifier(const nsACString& name) {
+        if (!mUniformInfoMap) {
+            // if the identifier-to-array-size map doesn't exist yet, build it now
+            mUniformInfoMap = new CStringToUniformInfoMap;
+            mUniformInfoMap->Init();
+            for (size_t i = 0; i < mAttachedShaders.Length(); i++) {
+                for (size_t j = 0; j < mAttachedShaders[i]->mUniforms.Length(); j++) {
+                    const WebGLMappedIdentifier& uniform = mAttachedShaders[i]->mUniforms[j];
+                    const WebGLUniformInfo& info = mAttachedShaders[i]->mUniformInfos[j];
+                    mUniformInfoMap->Put(uniform.mapped, info);
+                }
+            }
+        }
+
+        nsCString mutableName(name);
+        nsCString bracketPart;
+        bool hadBracketPart = SplitLastSquareBracket(mutableName, bracketPart);
+        // if there is a bracket, we're either an array or an entry in an array.
+        if (hadBracketPart)
+            mutableName.AppendLiteral("[0]");
+
+        WebGLUniformInfo info;
+        mUniformInfoMap->Get(mutableName, &info);
+        // we don't check if that Get failed, as if it did, it left info with default values
+
+        // if there is a bracket and it's not [0], then we're not an array, we're just an entry in an array
+        if (hadBracketPart && !bracketPart.EqualsLiteral("[0]")) {
+            info.isArray = false;
+            info.arraySize = 1;
+        }
+        return info;
+    }
+
     NS_DECL_ISUPPORTS
     NS_DECL_NSIWEBGLPROGRAM
 
 protected:
 
     WebGLuint mGLName;
     bool mLinkStatus;
     // attached shaders of the program object
     nsTArray<WebGLRefPtr<WebGLShader> > mAttachedShaders;
     CheckedUint32 mGeneration;
 
     // post-link data
     std::vector<bool> mAttribsInUse;
     WebGLMonotonicHandle mMonotonicHandle;
-    nsAutoPtr<CStringHash> mIdentifierMap, mIdentifierReverseMap;
+    nsAutoPtr<CStringMap> mIdentifierMap, mIdentifierReverseMap;
+    nsAutoPtr<CStringToUniformInfoMap> mUniformInfoMap;
     int mAttribMaxNameLength;
 };
 
 class WebGLRenderbuffer MOZ_FINAL
     : public nsIWebGLRenderbuffer
     , public WebGLRefCountedObject<WebGLRenderbuffer>
     , public WebGLRectangleObject
     , public WebGLContextBoundObject
@@ -2477,47 +2560,54 @@ public:
 };
 
 class WebGLUniformLocation MOZ_FINAL
     : public nsIWebGLUniformLocation
     , public WebGLContextBoundObject
     , public WebGLRefCountedObject<WebGLUniformLocation>
 {
 public:
-    WebGLUniformLocation(WebGLContext *context, WebGLProgram *program, GLint location)
+    WebGLUniformLocation(WebGLContext *context, WebGLProgram *program, GLint location, const WebGLUniformInfo& info)
         : WebGLContextBoundObject(context)
         , mProgram(program)
         , mProgramGeneration(program->Generation())
         , mLocation(location)
+        , mInfo(info)
     {
+        mElementSize = info.ElementSize();
         mMonotonicHandle = mContext->mUniformLocations.AppendElement(this);
     }
 
     ~WebGLUniformLocation() {
         DeleteOnce();
     }
 
     void Delete() {
         mProgram = nsnull;
         mContext->mUniformLocations.RemoveElement(mMonotonicHandle);
     }
 
+    const WebGLUniformInfo &Info() const { return mInfo; }
+
     WebGLProgram *Program() const { return mProgram; }
     GLint Location() const { return mLocation; }
     PRUint32 ProgramGeneration() const { return mProgramGeneration; }
+    int ElementSize() const { return mElementSize; }
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIWEBGLUNIFORMLOCATION
 protected:
     // nsRefPtr, not WebGLRefPtr, so that we don't prevent the program from being explicitly deleted.
     // we just want to avoid having a dangling pointer.
     nsRefPtr<WebGLProgram> mProgram;
 
     PRUint32 mProgramGeneration;
     GLint mLocation;
+    WebGLUniformInfo mInfo;
+    int mElementSize;
     WebGLMonotonicHandle mMonotonicHandle;
     friend class WebGLProgram;
 };
 
 class WebGLActiveInfo MOZ_FINAL
     : public nsIWebGLActiveInfo
 {
 public:
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -51,21 +51,16 @@
 #include "nsContentUtils.h"
 #include "nsDOMError.h"
 #include "nsLayoutUtils.h"
 
 #include "CanvasUtils.h"
 
 #include "jstypedarray.h"
 
-#if defined(USE_ANGLE)
-// shader translator
-#include "angle/ShaderLang.h"
-#endif
-
 #include "WebGLTexelConversions.h"
 #include "WebGLValidateStrings.h"
 
 // needed to check if current OS is lower than 10.7
 #if defined(MOZ_WIDGET_COCOA)
 #include "nsCocoaFeatures.h"
 #endif
 
@@ -3024,18 +3019,24 @@ WebGLContext::GetUniformLocation(nsIWebG
     NS_LossyConvertUTF16toASCII cname(name);
     nsCString mappedName;
     prog->MapIdentifier(cname, &mappedName);
 
     MakeContextCurrent();
     GLint intlocation = gl->fGetUniformLocation(progname, mappedName.get());
 
     WebGLUniformLocation *loc = nsnull;
-    if (intlocation >= 0)
-        NS_ADDREF(loc = new WebGLUniformLocation(this, prog, intlocation));
+    if (intlocation >= 0) {
+        WebGLUniformInfo info = prog->GetUniformInfoForMappedIdentifier(mappedName);
+        loc = new WebGLUniformLocation(this,
+                                       prog,
+                                       intlocation,
+                                       info);
+        NS_ADDREF(loc);
+    }
     *retval = loc;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::GetVertexAttrib(WebGLuint index, WebGLenum pname, nsIVariant **retval)
 {
     if (!IsContextStable())
@@ -4134,24 +4135,49 @@ WebGLContext::name(nsIWebGLUniformLocati
         return NS_OK;                                                           \
     }                                                                           \
                                                                                 \
     nsIWebGLUniformLocation* ploc = aLocation;                                  \
     OBTAIN_UNIFORM_LOCATION(#name ": location")                                 \
     if (JS_GetTypedArrayType(wa) != js::TypedArray::arrayType) {                \
         return ErrorInvalidOperation(#name ": array must be " #arrayType);      \
     }                                                                           \
-    if (JS_GetTypedArrayLength(wa) == 0 ||                                      \
-        JS_GetTypedArrayLength(wa) % cnt != 0) {                                \
-        return ErrorInvalidValue(#name ": array must be > 0 elements and have " \
-                                "a length multiple of %d", cnt);                \
+    int elementSize = location_object->ElementSize();                           \
+    if (cnt != elementSize) {                                                   \
+        return ErrorInvalidOperation(                                           \
+            #name ": this function expected a uniform of element size %d,"      \
+            " got a uniform of element size %d",                                \
+            cnt,                                                                \
+            elementSize);                                                       \
+    }                                                                           \
+    PRUint32 arrayLength = JS_GetTypedArrayLength(wa);                          \
+    const WebGLUniformInfo& info = location_object->Info();                     \
+    PRUint32 expectedArrayLength = cnt * info.arraySize;                        \
+    if (arrayLength < expectedArrayLength ||                                    \
+        (arrayLength % cnt))                                                    \
+    {                                                                           \
+        return ErrorInvalidValue("%s: expected an array of length a multiple of" \
+                                 " %d and at least %d, got an array of length %d", \
+                                 #name,                                         \
+                                 cnt,                                           \
+                                 expectedArrayLength,                           \
+                                 arrayLength);                                  \
+    }                                                                           \
+    if (!info.isArray &&                                                        \
+        arrayLength > expectedArrayLength) {                                    \
+        return ErrorInvalidOperation("%s: expected an array of length exactly %d" \
+                                     " (since this uniform is not an array uniform)," \
+                                     " got an array of length %d", \
+                                 #name,                                         \
+                                 expectedArrayLength,                           \
+                                 arrayLength);                                  \
     }                                                                           \
                                                                                 \
     MakeContextCurrent();                                                       \
-    gl->f##name(location, JS_GetTypedArrayLength(wa) / cnt,                     \
+    gl->f##name(location, info.arraySize,                                       \
                 static_cast<ptrType*>(JS_GetTypedArrayData(wa)));               \
     return NS_OK;                                                               \
 }
 
 #define SIMPLE_MATRIX_METHOD_UNIFORM(name, dim)                                 \
 NS_IMETHODIMP                                                                   \
 WebGLContext::name(nsIWebGLUniformLocation* aLocation, bool aTranspose,         \
                    const JS::Value& aValue, JSContext* aCx)                     \
@@ -4163,30 +4189,55 @@ WebGLContext::name(nsIWebGLUniformLocati
                                                                                 \
     if (!IsContextStable()) {                                                   \
         return NS_OK;                                                           \
     }                                                                           \
                                                                                 \
     nsIWebGLUniformLocation* ploc = aLocation;                                  \
     OBTAIN_UNIFORM_LOCATION(#name ": location")                                 \
     if (JS_GetTypedArrayType(wa) != js::TypedArray::TYPE_FLOAT32) {             \
-        return ErrorInvalidValue(#name ": array must be TYPE_FLOAT32");         \
+        return ErrorInvalidValue(#name ": array must be of Float32 type");      \
+    }                                                                           \
+    int elementSize = location_object->ElementSize();                           \
+    if (dim*dim != elementSize) {                                               \
+        return ErrorInvalidOperation(                                           \
+            #name ": this function expected a uniform of element size %d,"      \
+            " got a uniform of element size %d",                                \
+            dim*dim,                                                            \
+            elementSize);                                                       \
     }                                                                           \
-    if (JS_GetTypedArrayLength(wa) == 0 ||                                      \
-        JS_GetTypedArrayLength(wa) % (dim*dim) != 0) {                          \
-        return ErrorInvalidValue(#name ": array length must be >0 and "         \
-                                 "multiple of %d", dim*dim);                    \
+    PRUint32 arrayLength = JS_GetTypedArrayLength(wa);                          \
+    const WebGLUniformInfo& info = location_object->Info();                     \
+    PRUint32 expectedArrayLength = dim * dim * info.arraySize;                  \
+    if (arrayLength < expectedArrayLength ||                                    \
+        (arrayLength % (dim*dim)))                                              \
+    {                                                                           \
+        return ErrorInvalidValue("%s: expected an array of length a multiple of" \
+                                 " %d and at least %d, got an array of length %d", \
+                                 #name,                                         \
+                                 dim*dim,                                       \
+                                 expectedArrayLength,                           \
+                                 arrayLength);                                  \
+    }                                                                           \
+    if (!info.isArray &&                                          \
+        arrayLength > expectedArrayLength) {                                    \
+        return ErrorInvalidOperation("%s: expected an array of length exactly %d" \
+                                     " (since this uniform is not an array uniform)," \
+                                     " got an array of length %d", \
+                                 #name,                                         \
+                                 expectedArrayLength,                           \
+                                 arrayLength);                                  \
     }                                                                           \
     if (aTranspose) {                                                           \
         return ErrorInvalidValue(#name ": transpose must be FALSE as per the "  \
                                  "OpenGL ES 2.0 spec");                         \
     }                                                                           \
                                                                                 \
     MakeContextCurrent();                                                       \
-    gl->f##name(location, JS_GetTypedArrayLength(wa) / (dim*dim), false,        \
+    gl->f##name(location, info.arraySize, false,                  \
                 static_cast<WebGLfloat*>(JS_GetTypedArrayData(wa)));            \
     return NS_OK;                                                               \
 }
 
 #define SIMPLE_METHOD_UNIFORM_1(glname, name, t1)        \
 NS_IMETHODIMP WebGLContext::name(nsIWebGLUniformLocation *ploc, t1 a1) {      \
     if (!IsContextStable())                                    \
         return NS_OK;                                    \
@@ -4529,21 +4580,20 @@ WebGLContext::CompileShader(nsIWebGLShad
 
         const char *s = sourceCString.get();
 
         compiler = ShConstructCompiler((ShShaderType) shader->ShaderType(),
                                        SH_WEBGL_SPEC,
                                        targetShaderSourceLanguage,
                                        &resources);
 
-        int compileOptions = 0;
+        int compileOptions = SH_ATTRIBUTES_UNIFORMS;
         if (useShaderSourceTranslation) {
             compileOptions |= SH_OBJECT_CODE
-                            | SH_MAP_LONG_VARIABLE_NAMES
-                            | SH_ATTRIBUTES_UNIFORMS;
+                            | SH_MAP_LONG_VARIABLE_NAMES;
 #ifdef XP_MACOSX
             // work around bug 665578
             if (gl->WorkAroundDriverBugs() &&
                 !nsCocoaFeatures::OnLionOrLater() &&
                 gl->Vendor() == gl::GLContext::VendorATI)
             {
                 compileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS;
             }
@@ -4576,45 +4626,59 @@ WebGLContext::CompileShader(nsIWebGLShad
         ShGetInfo(compiler, SH_ACTIVE_UNIFORM_MAX_LENGTH, &uniform_max_length);
         int mapped_max_length = 0;
         ShGetInfo(compiler, SH_MAPPED_NAME_MAX_LENGTH, &mapped_max_length);
 
         shader->mAttribMaxNameLength = attrib_max_length;
 
         shader->mAttributes.Clear();
         shader->mUniforms.Clear();
+        shader->mUniformInfos.Clear();
+
         nsAutoArrayPtr<char> attribute_name(new char[attrib_max_length+1]);
         nsAutoArrayPtr<char> uniform_name(new char[uniform_max_length+1]);
         nsAutoArrayPtr<char> mapped_name(new char[mapped_max_length+1]);
 
+
+        for (int i = 0; i < num_uniforms; i++) {
+            int length, size;
+            ShDataType type;
+            ShGetActiveUniform(compiler, i,
+                                &length, &size, &type,
+                                uniform_name,
+                                mapped_name);
+            if (useShaderSourceTranslation) {
+                shader->mUniforms.AppendElement(WebGLMappedIdentifier(
+                                                    nsDependentCString(uniform_name),
+                                                    nsDependentCString(mapped_name)));
+            }
+
+            // we always query uniform info, regardless of useShaderSourceTranslation,
+            // as we need it to validate uniform setter calls, and it doesn't rely on
+            // shader translation.
+            shader->mUniformInfos.AppendElement(WebGLUniformInfo(
+                                                    size,
+                                                    length > 1 && mapped_name[length - 1] == ']',
+                                                    type));
+        }
+
         if (useShaderSourceTranslation) {
+
             for (int i = 0; i < num_attributes; i++) {
                 int length, size;
                 ShDataType type;
                 ShGetActiveAttrib(compiler, i,
                                   &length, &size, &type,
                                   attribute_name,
                                   mapped_name);
                 shader->mAttributes.AppendElement(WebGLMappedIdentifier(
                                                     nsDependentCString(attribute_name),
                                                     nsDependentCString(mapped_name)));
             }
 
-            for (int i = 0; i < num_uniforms; i++) {
-                int length, size;
-                ShDataType type;
-                ShGetActiveUniform(compiler, i,
-                                   &length, &size, &type,
-                                   uniform_name,
-                                   mapped_name);
-                shader->mUniforms.AppendElement(WebGLMappedIdentifier(
-                                                  nsDependentCString(uniform_name),
-                                                  nsDependentCString(mapped_name)));
-            }
-
             int len = 0;
             ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &len);
 
             nsCAutoString translatedSrc;
             translatedSrc.SetLength(len);
             ShGetObjectCode(compiler, translatedSrc.BeginWriting());
 
             nsPromiseFlatCString translatedSrc2(translatedSrc);
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -56,16 +56,17 @@ using namespace mozilla;
 /*
  * Pull data out of the program, post-linking
  */
 bool
 WebGLProgram::UpdateInfo()
 {
     mIdentifierMap = nsnull;
     mIdentifierReverseMap = nsnull;
+    mUniformInfoMap = nsnull;
 
     mAttribMaxNameLength = 0;
 
     for (size_t i = 0; i < mAttachedShaders.Length(); i++)
         mAttribMaxNameLength = NS_MAX(mAttribMaxNameLength, mAttachedShaders[i]->mAttribMaxNameLength);
 
     GLint attribCount;
     mContext->gl->fGetProgramiv(mGLName, LOCAL_GL_ACTIVE_ATTRIBUTES, &attribCount);
--- a/content/canvas/test/webgl/failing_tests_windows.txt
+++ b/content/canvas/test/webgl/failing_tests_windows.txt
@@ -1,1 +0,0 @@
-conformance/more/functions/uniformfArrayLen1.html
--- a/content/canvas/test/webgl/test_webgl_conformance_test_suite.html
+++ b/content/canvas/test/webgl/test_webgl_conformance_test_suite.html
@@ -442,26 +442,16 @@ function start() {
   while(indexOfEmptyFilename != -1) {
     testsExpectedToFail.splice(indexOfEmptyFilename, 1);
     indexOfEmptyFilename = testsExpectedToFail.indexOf("");
   }
 
   if (kIsWindows && !kIsWindowsVistaOrHigher)
     testsExpectedToFail.push('conformance/textures/texture-mips.html');
 
-  if (kIsMac && kDarwinVersion < 11.0) {    // Darwin 11 == Mac OS 10.7
-    testsExpectedToFail.push('conformance/more/functions/uniformfBadArgs.html');
-    testsExpectedToFail.push('conformance/more/functions/uniformiBadArgs.html');
-  }
-
-  if (kIsMac && kDarwinVersion >= 11.0) {
-    testsExpectedToFail.push('conformance/textures/texture-mips.html');
-    testsExpectedToFail.push('conformance/textures/texture-npot.html');
-  }
-
   var testsToIgnore = [];
 
   runTestSuite();
 }
 
 </script>
 </head>
 <body onload="start();">