Bug 1237193 - Fix WebGL getActiveUniforms return type. r=jgilbert, r=smaug
authorEthan Lin <ethlin@mozilla.com>
Mon, 15 Feb 2016 15:14:00 +0100
changeset 331299 a3f46ba96f9572ad00ce1190f3b22a55117de8fe
parent 331298 46180e3cd0c6adda64977bd6ecd82aec201d6f3a
child 331300 a24be316086fb99ffd3e0ce75220d2074e9b8174
push id10956
push userjolesen@mozilla.com
push dateTue, 16 Feb 2016 19:12:12 +0000
reviewersjgilbert, smaug
bugs1237193
milestone47.0a1
Bug 1237193 - Fix WebGL getActiveUniforms return type. r=jgilbert, r=smaug
dom/canvas/WebGL2Context.h
dom/canvas/WebGL2ContextUniforms.cpp
dom/webidl/WebGL2RenderingContext.webidl
--- a/dom/canvas/WebGL2Context.h
+++ b/dom/canvas/WebGL2Context.h
@@ -355,19 +355,22 @@ public:
     void BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer, GLintptr offset, GLsizeiptr size);
 */
     virtual JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv) override;
     void GetIndexedParameter(GLenum target, GLuint index,
                              dom::Nullable<dom::OwningWebGLBufferOrLongLong>& retval);
     void GetUniformIndices(WebGLProgram* program,
                            const dom::Sequence<nsString>& uniformNames,
                            dom::Nullable< nsTArray<GLuint> >& retval);
-    void GetActiveUniforms(WebGLProgram* program,
-                           const dom::Sequence<GLuint>& uniformIndices, GLenum pname,
-                           dom::Nullable< nsTArray<GLint> >& retval);
+    void GetActiveUniforms(JSContext* cx,
+                           WebGLProgram* program,
+                           const dom::Sequence<GLuint>& uniformIndices,
+                           GLenum pname,
+                           JS::MutableHandleValue retval);
+
     GLuint GetUniformBlockIndex(WebGLProgram* program, const nsAString& uniformBlockName);
     void GetActiveUniformBlockParameter(JSContext*, WebGLProgram* program,
                                         GLuint uniformBlockIndex, GLenum pname,
                                         dom::Nullable<dom::OwningUnsignedLongOrUint32ArrayOrBoolean>& retval,
                                         ErrorResult& rv);
     void GetActiveUniformBlockName(WebGLProgram* program, GLuint uniformBlockIndex,
                                    nsAString& retval);
     void UniformBlockBinding(WebGLProgram* program, GLuint uniformBlockIndex,
--- a/dom/canvas/WebGL2ContextUniforms.cpp
+++ b/dom/canvas/WebGL2ContextUniforms.cpp
@@ -313,45 +313,101 @@ WebGL2Context::GetUniformIndices(WebGLPr
         return;
 
     if (!uniformNames.Length())
         return;
 
     program->GetUniformIndices(uniformNames, retval);
 }
 
+static bool
+ValidateUniformEnum(WebGLContext* webgl, GLenum pname, const char* info)
+{
+    switch (pname) {
+    case LOCAL_GL_UNIFORM_TYPE:
+    case LOCAL_GL_UNIFORM_SIZE:
+    case LOCAL_GL_UNIFORM_BLOCK_INDEX:
+    case LOCAL_GL_UNIFORM_OFFSET:
+    case LOCAL_GL_UNIFORM_ARRAY_STRIDE:
+    case LOCAL_GL_UNIFORM_MATRIX_STRIDE:
+    case LOCAL_GL_UNIFORM_IS_ROW_MAJOR:
+        return true;
+
+    default:
+        webgl->ErrorInvalidEnum("%s: invalid pname: %s", info, webgl->EnumName(pname));
+        return false;
+    }
+}
+
 void
-WebGL2Context::GetActiveUniforms(WebGLProgram* program,
+WebGL2Context::GetActiveUniforms(JSContext* cx,
+                                 WebGLProgram* program,
                                  const dom::Sequence<GLuint>& uniformIndices,
                                  GLenum pname,
-                                 dom::Nullable< nsTArray<GLint> >& retval)
+                                 JS::MutableHandleValue retval)
 {
-    retval.SetNull();
+    retval.set(JS::NullValue());
     if (IsContextLost())
         return;
 
-    if (pname == LOCAL_GL_UNIFORM_NAME_LENGTH) {
-        ErrorInvalidEnumInfo("getActiveUniforms: pname", pname);
+    if (!ValidateUniformEnum(this, pname, "getActiveUniforms"))
         return;
-    }
 
     if (!ValidateObject("getActiveUniforms: program", program))
         return;
 
     size_t count = uniformIndices.Length();
     if (!count)
         return;
 
     GLuint progname = program->mGLName;
-    nsTArray<GLint>& arr = retval.SetValue();
-    arr.SetLength(count);
+    Vector<GLint> samples;
+    if (!samples.resize(count)) {
+        return;
+    }
 
     MakeContextCurrent();
     gl->fGetActiveUniformsiv(progname, count, uniformIndices.Elements(), pname,
-                             arr.Elements());
+                             samples.begin());
+
+    JS::Rooted<JSObject*> array(cx, JS_NewArrayObject(cx, count));
+    if (!array) {
+        return;
+    }
+
+    switch (pname) {
+    case LOCAL_GL_UNIFORM_TYPE:
+    case LOCAL_GL_UNIFORM_SIZE:
+    case LOCAL_GL_UNIFORM_BLOCK_INDEX:
+    case LOCAL_GL_UNIFORM_OFFSET:
+    case LOCAL_GL_UNIFORM_ARRAY_STRIDE:
+    case LOCAL_GL_UNIFORM_MATRIX_STRIDE:
+        for (uint32_t i = 0; i < count; ++i) {
+            JS::RootedValue value(cx);
+            value = JS::Int32Value(samples[i]);
+            if (!JS_DefineElement(cx, array, i, value, JSPROP_ENUMERATE)) {
+                return;
+            }
+        }
+        break;
+    case LOCAL_GL_UNIFORM_IS_ROW_MAJOR:
+        for (uint32_t i = 0; i < count; ++i) {
+            JS::RootedValue value(cx);
+            value = JS::BooleanValue(samples[i]);
+            if (!JS_DefineElement(cx, array, i, value, JSPROP_ENUMERATE)) {
+                return;
+            }
+        }
+        break;
+
+    default:
+        return;
+    }
+
+    retval.setObjectOrNull(array);
 }
 
 GLuint
 WebGL2Context::GetUniformBlockIndex(WebGLProgram* program,
                                     const nsAString& uniformBlockName)
 {
     if (IsContextLost())
         return 0;
--- a/dom/webidl/WebGL2RenderingContext.webidl
+++ b/dom/webidl/WebGL2RenderingContext.webidl
@@ -470,17 +470,17 @@ interface WebGL2RenderingContext : WebGL
     /* Uniform Buffer Objects and Transform Feedback Buffers */
     void bindBufferBase(GLenum target, GLuint index, WebGLBuffer? buffer);
     void bindBufferRange(GLenum target, GLuint index, WebGLBuffer? buffer, GLintptr offset, GLsizeiptr size);
     // Return from getIndexedParameter is WebGLBuffer or GLintptr or GLsizeiptr) but
     // GLintptr and GLsizeiptr are the same underlying type of long long, so only specify
     // GLintptr here, otherwise interface generator returns error.
     (WebGLBuffer or GLintptr)? getIndexedParameter(GLenum target, GLuint index);
     sequence<GLuint>? getUniformIndices(WebGLProgram? program, sequence<DOMString> uniformNames);
-    sequence<GLint>? getActiveUniforms(WebGLProgram? program, sequence<GLuint> uniformIndices, GLenum pname);
+    any getActiveUniforms(WebGLProgram? program, sequence<GLuint> uniformIndices, GLenum pname);
     GLuint getUniformBlockIndex(WebGLProgram? program, DOMString uniformBlockName);
     [Throws]
     (GLuint or Uint32Array or GLboolean)? getActiveUniformBlockParameter(WebGLProgram? program, GLuint uniformBlockIndex, GLenum pname);
     DOMString? getActiveUniformBlockName(WebGLProgram? program, GLuint uniformBlockIndex);
     void uniformBlockBinding(WebGLProgram? program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
 
     /* Vertex Array Objects */
     WebGLVertexArrayObject? createVertexArray();