Bug 747619 - fix uniform setter validation: allow partial uniform array updates - r=jgilbert
☠☠ backed out by 7315f04e0303 ☠ ☠
authorBenoit Jacob <bjacob@mozilla.com>
Thu, 03 May 2012 15:57:25 -0400
changeset 93024 b13c1d8d2cda2861101c658efcac7db4326ef9da
parent 93023 7cd83841136cad341cf947adb82ffd50155a2e6a
child 93025 fc99eb1e232b915bc1bb063f59c2f5bcc92144f6
push id22608
push useremorley@mozilla.com
push dateFri, 04 May 2012 12:47:48 +0000
treeherdermozilla-central@9ebf3dc839c5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert
bugs747619
milestone15.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 747619 - fix uniform setter validation: allow partial uniform array updates - r=jgilbert
content/canvas/src/WebGLContextGL.cpp
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -4159,125 +4159,124 @@ GetFloat32Array(JSContext* aCx, const JS
     if (!mCurrentProgram) \
         return ErrorInvalidOperation("%s: no program is currently bound", info); \
     if (mCurrentProgram != location_object->Program()) \
         return ErrorInvalidOperation("%s: this uniform location doesn't correspond to the current program", info); \
     if (mCurrentProgram->Generation() != location_object->ProgramGeneration())            \
         return ErrorInvalidOperation("%s: This uniform location is obsolete since the program has been relinked", info); \
     GLint location = location_object->Location();
 
-#define SIMPLE_ARRAY_METHOD_UNIFORM(name, cnt, arrayType, ptrType)              \
+#define SIMPLE_ARRAY_METHOD_UNIFORM(name, expectedElemSize, arrayType, ptrType)              \
 NS_IMETHODIMP                                                                   \
 WebGLContext::name(nsIWebGLUniformLocation *aLocation, const JS::Value& aValue, \
                    JSContext* aCx)                                              \
 {                                                                               \
     JSObject* wa = GetTypedArray<JS_Is ## arrayType ## Array, JS_New ## arrayType ## ArrayFromArray>(aCx, aValue); \
     if (!wa) {                                                                  \
         return NS_ERROR_FAILURE;                                                \
     }                                                                           \
                                                                                 \
     if (!IsContextStable()) {                                                   \
         return NS_OK;                                                           \
     }                                                                           \
                                                                                 \
     nsIWebGLUniformLocation* ploc = aLocation;                                  \
     OBTAIN_UNIFORM_LOCATION(#name ": location")                                 \
-    int elementSize = location_object->ElementSize();                           \
-    if (cnt != elementSize) {                                                   \
+    int uniformElemSize = location_object->ElementSize();                           \
+    if (expectedElemSize != uniformElemSize) {                                                   \
         return ErrorInvalidOperation(                                           \
             #name ": this function expected a uniform of element size %d,"      \
             " got a uniform of element size %d",                                \
-            cnt,                                                                \
-            elementSize);                                                       \
+            expectedElemSize,                                                                \
+            uniformElemSize);                                                       \
     }                                                                           \
     PRUint32 arrayLength = JS_GetTypedArrayLength(wa, aCx);                     \
     const WebGLUniformInfo& info = location_object->Info();                     \
-    PRUint32 expectedArrayLength = cnt * info.arraySize;                        \
-    if (arrayLength < expectedArrayLength ||                                    \
-        (arrayLength % cnt))                                                    \
+    if (arrayLength == 0 ||                                                     \
+        arrayLength % expectedElemSize)                                                      \
     {                                                                           \
         return ErrorInvalidValue("%s: expected an array of length a multiple of" \
-                                 " %d and at least %d, got an array of length %d", \
+                                 " %d, got an array of length %d",              \
                                  #name,                                         \
-                                 cnt,                                           \
-                                 expectedArrayLength,                           \
+                                 expectedElemSize,                                           \
                                  arrayLength);                                  \
     }                                                                           \
     if (!info.isArray &&                                                        \
-        arrayLength > expectedArrayLength) {                                    \
+        arrayLength != expectedElemSize) {                                                   \
         return ErrorInvalidOperation("%s: expected an array of length exactly %d" \
                                      " (since this uniform is not an array uniform)," \
-                                     " got an array of length %d", \
+                                     " got an array of length %d",              \
                                  #name,                                         \
-                                 expectedArrayLength,                           \
+                                 expectedElemSize,                                           \
                                  arrayLength);                                  \
     }                                                                           \
                                                                                 \
     MakeContextCurrent();                                                       \
-    gl->f##name(location, info.arraySize,                                       \
-                static_cast<ptrType*>(JS_GetArrayBufferViewData(wa, aCx)));     \
+    PRUint32 numElementsToUpload = NS_MIN(info.arraySize, arrayLength/expectedElemSize);     \
+    gl->f##name(location, numElementsToUpload,                                  \
+                 static_cast<ptrType*>(JS_GetArrayBufferViewData(wa, aCx)));    \
     return NS_OK;                                                               \
 }
 
 #define SIMPLE_MATRIX_METHOD_UNIFORM(name, dim)                                 \
 NS_IMETHODIMP                                                                   \
 WebGLContext::name(nsIWebGLUniformLocation* aLocation, bool aTranspose,         \
                    const JS::Value& aValue, JSContext* aCx)                     \
 {                                                                               \
+    int expectedElemSize = (dim)*(dim);                                                     \
     JSObject* wa = GetFloat32Array(aCx, aValue);                                \
     if (!wa) {                                                                  \
         return NS_ERROR_FAILURE;                                                \
     }                                                                           \
                                                                                 \
     if (!IsContextStable()) {                                                   \
         return NS_OK;                                                           \
     }                                                                           \
                                                                                 \
     nsIWebGLUniformLocation* ploc = aLocation;                                  \
     OBTAIN_UNIFORM_LOCATION(#name ": location")                                 \
     if (!wa || !JS_IsFloat32Array(wa, aCx)) {                                   \
         return ErrorInvalidValue(#name ": array must be of Float32 type");      \
     }                                                                           \
-    int elementSize = location_object->ElementSize();                           \
-    if (dim*dim != elementSize) {                                               \
+    int uniformElemSize = location_object->ElementSize();                           \
+    if (expectedElemSize != uniformElemSize) {                                               \
         return ErrorInvalidOperation(                                           \
             #name ": this function expected a uniform of element size %d,"      \
             " got a uniform of element size %d",                                \
-            dim*dim,                                                            \
-            elementSize);                                                       \
+            expectedElemSize,                                                            \
+            uniformElemSize);                                                       \
     }                                                                           \
     PRUint32 arrayLength = JS_GetTypedArrayLength(wa, aCx);                     \
     const WebGLUniformInfo& info = location_object->Info();                     \
-    PRUint32 expectedArrayLength = dim * dim * info.arraySize;                  \
-    if (arrayLength < expectedArrayLength ||                                    \
-        (arrayLength % (dim*dim)))                                              \
+    if (arrayLength == 0 ||                                                     \
+        arrayLength % expectedElemSize)                                                \
     {                                                                           \
         return ErrorInvalidValue("%s: expected an array of length a multiple of" \
-                                 " %d and at least %d, got an array of length %d", \
+                                 " %d, got an array of length %d",              \
                                  #name,                                         \
-                                 dim*dim,                                       \
-                                 expectedArrayLength,                           \
+                                 expectedElemSize,                                       \
                                  arrayLength);                                  \
     }                                                                           \
-    if (!info.isArray &&                                          \
-        arrayLength > expectedArrayLength) {                                    \
+    if (!info.isArray &&                                                        \
+        arrayLength != expectedElemSize) {                                               \
         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,                           \
+                                 expectedElemSize,                           \
                                  arrayLength);                                  \
     }                                                                           \
     if (aTranspose) {                                                           \
         return ErrorInvalidValue(#name ": transpose must be FALSE as per the "  \
                                  "OpenGL ES 2.0 spec");                         \
     }                                                                           \
                                                                                 \
     MakeContextCurrent();                                                       \
-    gl->f##name(location, info.arraySize, false,                  \
+    PRUint32 numElementsToUpload = NS_MIN(info.arraySize, arrayLength/(expectedElemSize));  \
+    gl->f##name(location, numElementsToUpload, false,                           \
                 static_cast<WebGLfloat*>(JS_GetArrayBufferViewData(wa, aCx)));  \
     return NS_OK;                                                               \
 }
 
 #define SIMPLE_METHOD_UNIFORM_1(glname, name, t1)        \
 NS_IMETHODIMP WebGLContext::name(nsIWebGLUniformLocation *ploc, t1 a1) {      \
     if (!IsContextStable())                                    \
         return NS_OK;                                    \