Bug 1048747 - [WebGL2] Implement uniform block/buffer. r=jgilbert, r=smaug
☠☠ backed out by da9e07d0a41c ☠ ☠
authorDan Glastonbury <dglastonbury@mozilla.com>
Mon, 15 Dec 2014 10:31:24 +1000
changeset 219649 ee50dac0cb7ebc7efaf9f176f4c64cbe1e925d50
parent 219648 6461117552cd2247bc0f491773dfa1bbadc505e2
child 219650 c29cfb6929e51207dde66402184f7c805ff4546c
push id52896
push userdglastonbury@mozilla.com
push dateMon, 15 Dec 2014 02:35:23 +0000
treeherdermozilla-inbound@ee50dac0cb7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert, smaug
bugs1048747
milestone37.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 1048747 - [WebGL2] Implement uniform block/buffer. 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
@@ -9,16 +9,20 @@
 #include "WebGLContext.h"
 
 namespace mozilla {
 
 class WebGLSampler;
 class WebGLSync;
 class WebGLTransformFeedback;
 class WebGLVertexArrayObject;
+namespace dom {
+class OwningUnsignedLongOrUint32ArrayOrBoolean;
+class OwningWebGLBufferOrLongLong;
+}
 
 class WebGL2Context
     : public WebGLContext
 {
 public:
 
     virtual ~WebGL2Context();
 
@@ -226,24 +230,33 @@ public:
 
     // -------------------------------------------------------------------------
     // Uniform Buffer Objects and Transform Feedback Buffers - WebGL2ContextUniforms.cpp
     // TODO(djg): Implemented in WebGLContext
 /*
     void BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer);
     void BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer, GLintptr offset, GLsizeiptr size);
 */
-    void GetIndexedParameter(JSContext*, GLenum target, GLuint index, JS::MutableHandleValue 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,
+    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);
     GLuint GetUniformBlockIndex(WebGLProgram* program, const nsAString& uniformBlockName);
-    void GetActiveUniformBlockParameter(JSContext*, WebGLProgram* program, GLuint uniformBlockIndex, GLenum pname, JS::MutableHandleValue retval);
-    void GetActiveUniformBlockName(WebGLProgram* program, GLuint uniformBlockIndex, dom::DOMString& retval);
-    void UniformBlockBinding(WebGLProgram* program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+    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,
+                             GLuint uniformBlockBinding);
 
 
     // -------------------------------------------------------------------------
     // Vertex Array Object - WebGL2ContextVAOs.cpp
     // TODO(djg): Implemented in WebGLContext
 /*
     already_AddRefed<WebGLVertexArrayObject> CreateVertexArray();
     void DeleteVertexArray(WebGLVertexArrayObject* vertexArray);
--- a/dom/canvas/WebGL2ContextUniforms.cpp
+++ b/dom/canvas/WebGL2ContextUniforms.cpp
@@ -1,17 +1,20 @@
 /* -*- 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 "WebGL2Context.h"
 #include "GLContext.h"
+#include "WebGLContext.h"
+#include "WebGLProgram.h"
 #include "WebGLVertexArray.h"
 #include "WebGLVertexAttribData.h"
+#include "mozilla/dom/WebGL2RenderingContextBinding.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 typedef union { GLint i; GLfloat f; GLuint u; } fi_t;
 
 static inline
 GLfloat PuntToFloat(GLint i)
@@ -25,70 +28,75 @@ static inline
 GLfloat PuntToFloat(GLuint u)
 {
    fi_t tmp;
    tmp.u = u;
    return tmp.f;
 }
 
 bool
-WebGL2Context::ValidateAttribPointerType(bool integerMode, GLenum type, GLsizei* alignment, const char* info)
+WebGL2Context::ValidateAttribPointerType(bool integerMode, GLenum type,
+                                         GLsizei* out_alignment, const char* info)
 {
-    MOZ_ASSERT(alignment);
+    MOZ_ASSERT(out_alignment);
 
     switch (type) {
     case LOCAL_GL_BYTE:
     case LOCAL_GL_UNSIGNED_BYTE:
-        *alignment = 1;
+        *out_alignment = 1;
         return true;
 
     case LOCAL_GL_SHORT:
     case LOCAL_GL_UNSIGNED_SHORT:
-        *alignment = 2;
+        *out_alignment = 2;
         return true;
 
     case LOCAL_GL_INT:
     case LOCAL_GL_UNSIGNED_INT:
-        *alignment = 4;
+        *out_alignment = 4;
         return true;
     }
 
     if (!integerMode) {
         switch (type) {
         case LOCAL_GL_HALF_FLOAT:
-            *alignment = 2;
+            *out_alignment = 2;
             return true;
 
         case LOCAL_GL_FLOAT:
         case LOCAL_GL_FIXED:
         case LOCAL_GL_INT_2_10_10_10_REV:
         case LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV:
-            *alignment = 4;
+            *out_alignment = 4;
             return true;
         }
     }
 
     ErrorInvalidEnum("%s: invalid enum value 0x%x", info, type);
     return false;
 }
 
 // -------------------------------------------------------------------------
 // Uniforms and attributes
 
 void
-WebGL2Context::VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset)
+WebGL2Context::VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride,
+                                    GLintptr offset)
 {
     if (IsContextLost())
         return;
 
     if (!ValidateAttribIndex(index, "vertexAttribIPointer"))
         return;
 
-    if (!ValidateAttribPointer(true, index, size, type, LOCAL_GL_FALSE, stride, offset, "vertexAttribIPointer"))
+    if (!ValidateAttribPointer(true, index, size, type, LOCAL_GL_FALSE, stride, offset,
+                               "vertexAttribIPointer"))
+    {
         return;
+    }
 
     MOZ_ASSERT(mBoundVertexArray);
     mBoundVertexArray->EnsureAttrib(index);
 
     InvalidateBufferFetching();
 
     WebGLVertexAttribData& vd = mBoundVertexArray->mAttribs[index];
 
@@ -118,113 +126,130 @@ WebGL2Context::Uniform2ui(WebGLUniformLo
 
 void
 WebGL2Context::Uniform3ui(WebGLUniformLocation* location, GLuint v0, GLuint v1, GLuint v2)
 {
     MOZ_CRASH("Not Implemented.");
 }
 
 void
-WebGL2Context::Uniform4ui(WebGLUniformLocation* location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+WebGL2Context::Uniform4ui(WebGLUniformLocation* location, GLuint v0, GLuint v1,
+                          GLuint v2, GLuint v3)
 {
     MOZ_CRASH("Not Implemented.");
 }
 
 void
-WebGL2Context::Uniform1uiv(WebGLUniformLocation* location, const dom::Sequence<GLuint>& value)
+WebGL2Context::Uniform1uiv(WebGLUniformLocation* location,
+                           const dom::Sequence<GLuint>& value)
 {
     MOZ_CRASH("Not Implemented.");
 }
 
 void
-WebGL2Context::Uniform2uiv(WebGLUniformLocation* location, const dom::Sequence<GLuint>& value)
+WebGL2Context::Uniform2uiv(WebGLUniformLocation* location,
+                           const dom::Sequence<GLuint>& value)
 {
     MOZ_CRASH("Not Implemented.");
 }
 
 void
-WebGL2Context::Uniform3uiv(WebGLUniformLocation* location, const dom::Sequence<GLuint>& value)
+WebGL2Context::Uniform3uiv(WebGLUniformLocation* location,
+                           const dom::Sequence<GLuint>& value)
 {
     MOZ_CRASH("Not Implemented.");
 }
 
 void
-WebGL2Context::Uniform4uiv(WebGLUniformLocation* location, const dom::Sequence<GLuint>& value)
+WebGL2Context::Uniform4uiv(WebGLUniformLocation* location,
+                           const dom::Sequence<GLuint>& value)
 {
     MOZ_CRASH("Not Implemented.");
 }
 
 void
-WebGL2Context::UniformMatrix2x3fv(WebGLUniformLocation* location, bool transpose, const dom::Float32Array& value)
+WebGL2Context::UniformMatrix2x3fv(WebGLUniformLocation* location, bool transpose,
+                                  const dom::Float32Array& value)
 {
     MOZ_CRASH("Not Implemented.");
 }
 
 void
-WebGL2Context::UniformMatrix2x3fv(WebGLUniformLocation* location, bool transpose, const dom::Sequence<GLfloat>& value)
+WebGL2Context::UniformMatrix2x3fv(WebGLUniformLocation* location, bool transpose,
+                                  const dom::Sequence<GLfloat>& value)
 {
     MOZ_CRASH("Not Implemented.");
 }
 
 void
-WebGL2Context::UniformMatrix3x2fv(WebGLUniformLocation* location, bool transpose, const dom::Float32Array& value)
+WebGL2Context::UniformMatrix3x2fv(WebGLUniformLocation* location, bool transpose,
+                                  const dom::Float32Array& value)
 {
     MOZ_CRASH("Not Implemented.");
 }
 
 void
-WebGL2Context::UniformMatrix3x2fv(WebGLUniformLocation* location, bool transpose, const dom::Sequence<GLfloat>& value)
+WebGL2Context::UniformMatrix3x2fv(WebGLUniformLocation* location, bool transpose,
+                                  const dom::Sequence<GLfloat>& value)
 {
     MOZ_CRASH("Not Implemented.");
 }
 
 void
-WebGL2Context::UniformMatrix2x4fv(WebGLUniformLocation* location, bool transpose, const dom::Float32Array& value)
+WebGL2Context::UniformMatrix2x4fv(WebGLUniformLocation* location, bool transpose,
+                                  const dom::Float32Array& value)
 {
     MOZ_CRASH("Not Implemented.");
 }
 
 void
-WebGL2Context::UniformMatrix2x4fv(WebGLUniformLocation* location, bool transpose, const dom::Sequence<GLfloat>& value)
+WebGL2Context::UniformMatrix2x4fv(WebGLUniformLocation* location, bool transpose,
+                                  const dom::Sequence<GLfloat>& value)
 {
     MOZ_CRASH("Not Implemented.");
 }
 
 void
-WebGL2Context::UniformMatrix4x2fv(WebGLUniformLocation* location, bool transpose, const dom::Float32Array& value)
+WebGL2Context::UniformMatrix4x2fv(WebGLUniformLocation* location, bool transpose,
+                                  const dom::Float32Array& value)
 {
     MOZ_CRASH("Not Implemented.");
 }
 
 void
-WebGL2Context::UniformMatrix4x2fv(WebGLUniformLocation* location, bool transpose, const dom::Sequence<GLfloat>& value)
+WebGL2Context::UniformMatrix4x2fv(WebGLUniformLocation* location, bool transpose,
+                                  const dom::Sequence<GLfloat>& value)
 {
     MOZ_CRASH("Not Implemented.");
 }
 
 void
-WebGL2Context::UniformMatrix3x4fv(WebGLUniformLocation* location, bool transpose, const dom::Float32Array& value)
+WebGL2Context::UniformMatrix3x4fv(WebGLUniformLocation* location, bool transpose,
+                                  const dom::Float32Array& value)
 {
     MOZ_CRASH("Not Implemented.");
 }
 
 void
-WebGL2Context::UniformMatrix3x4fv(WebGLUniformLocation* location, bool transpose, const dom::Sequence<GLfloat>& value)
+WebGL2Context::UniformMatrix3x4fv(WebGLUniformLocation* location, bool transpose,
+                                  const dom::Sequence<GLfloat>& value)
 {
     MOZ_CRASH("Not Implemented.");
 }
 
 void
-WebGL2Context::UniformMatrix4x3fv(WebGLUniformLocation* location, bool transpose, const dom::Float32Array& value)
+WebGL2Context::UniformMatrix4x3fv(WebGLUniformLocation* location, bool transpose,
+                                  const dom::Float32Array& value)
 {
     MOZ_CRASH("Not Implemented.");
 }
 
 void
-WebGL2Context::UniformMatrix4x3fv(WebGLUniformLocation* location, bool transpose, const dom::Sequence<GLfloat>& value)
+WebGL2Context::UniformMatrix4x3fv(WebGLUniformLocation* location, bool transpose,
+                                  const dom::Sequence<GLfloat>& value)
 {
     MOZ_CRASH("Not Implemented.");
 }
 
 void
 WebGL2Context::VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
 {
     if (IsContextLost())
@@ -304,60 +329,250 @@ WebGL2Context::VertexAttribI4uiv(GLuint 
     VertexAttribI4uiv(index, v.Length(), v.Elements());
 }
 
 // -------------------------------------------------------------------------
 // Uniform Buffer Objects and Transform Feedback Buffers
 // TODO(djg): Implemented in WebGLContext
 /*
     void BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer);
-    void BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer, GLintptr offset, GLsizeiptr size);
+    void BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer,
+                         GLintptr offset, GLsizeiptr size);
 */
 
+/* This doesn't belong here. It's part of state querying */
 void
-WebGL2Context::GetIndexedParameter(JSContext*, GLenum target, GLuint index, JS::MutableHandleValue retval)
+WebGL2Context::GetIndexedParameter(GLenum target, GLuint index,
+                                   dom::Nullable<dom::OwningWebGLBufferOrLongLong>& retval)
 {
-    MOZ_CRASH("Not Implemented.");
+    retval.SetNull();
+    if (IsContextLost())
+        return;
+
+    GLint64 data = 0;
+
+    MakeContextCurrent();
+
+    switch (target) {
+    case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+        if (index >= mGLMaxTransformFeedbackSeparateAttribs)
+            return ErrorInvalidValue("getIndexedParameter: index should be less than "
+                                     "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS");
+
+        retval.SetValue().SetAsWebGLBuffer() =
+            mBoundTransformFeedbackBuffers[index].get();
+        return;
+
+    case LOCAL_GL_UNIFORM_BUFFER_BINDING:
+        if (index >= mGLMaxUniformBufferBindings)
+            return ErrorInvalidValue("getIndexedParameter: index should be than "
+                                     "MAX_UNIFORM_BUFFER_BINDINGS");
+
+        retval.SetValue().SetAsWebGLBuffer() = mBoundUniformBuffers[index].get();
+        return;
+
+    case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_START:
+    case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
+    case LOCAL_GL_UNIFORM_BUFFER_START:
+    case LOCAL_GL_UNIFORM_BUFFER_SIZE:
+        gl->fGetInteger64i_v(target, index, &data);
+        retval.SetValue().SetAsLongLong() = data;
+        return;
+    }
+
+    ErrorInvalidEnumInfo("getIndexedParameter: target", target);
 }
 
 void
 WebGL2Context::GetUniformIndices(WebGLProgram* program,
                                  const dom::Sequence<nsString>& uniformNames,
                                  dom::Nullable< nsTArray<GLuint> >& retval)
 {
-    MOZ_CRASH("Not Implemented.");
+    retval.SetNull();
+    if (IsContextLost())
+        return;
+
+    if (!ValidateObject("getUniformIndices: program", program))
+        return;
+
+    if (!uniformNames.Length())
+        return;
+
+    GLuint progname = program->GLName();
+    size_t count = uniformNames.Length();
+    nsTArray<GLuint>& arr = retval.SetValue();
+
+    MakeContextCurrent();
+
+    for (size_t n = 0; n < count; n++) {
+        NS_LossyConvertUTF16toASCII name(uniformNames[n]);
+        //        const GLchar* glname = name.get();
+        const GLchar* glname = nullptr;
+        name.BeginReading(glname);
+
+        GLuint index = 0;
+        gl->fGetUniformIndices(progname, 1, &glname, &index);
+        arr.AppendElement(index);
+    }
 }
 
 void
 WebGL2Context::GetActiveUniforms(WebGLProgram* program,
                                  const dom::Sequence<GLuint>& uniformIndices,
                                  GLenum pname,
                                  dom::Nullable< nsTArray<GLint> >& retval)
 {
-    MOZ_CRASH("Not Implemented.");
+    retval.SetNull();
+    if (IsContextLost())
+        return;
+
+    if (!ValidateObject("getActiveUniforms: program", program))
+        return;
+
+    size_t count = uniformIndices.Length();
+    if (!count)
+        return;
+
+    GLuint progname = program->GLName();
+    nsTArray<GLint>& arr = retval.SetValue();
+    arr.SetLength(count);
+
+    MakeContextCurrent();
+    gl->fGetActiveUniformsiv(progname, count, uniformIndices.Elements(), pname,
+                             arr.Elements());
 }
 
 GLuint
-WebGL2Context::GetUniformBlockIndex(WebGLProgram* program, const nsAString& uniformBlockName)
+WebGL2Context::GetUniformBlockIndex(WebGLProgram* program,
+                                    const nsAString& uniformBlockName)
 {
-    MOZ_CRASH("Not Implemented.");
-    return 0;
+    if (IsContextLost())
+        return 0;
+
+    if (!ValidateObject("getUniformBlockIndex: program", program))
+        return 0;
+
+    if (!ValidateGLSLVariableName(uniformBlockName, "getUniformBlockIndex"))
+        return 0;
+
+    NS_LossyConvertUTF16toASCII cname(uniformBlockName);
+    nsCString mappedName;
+    program->MapIdentifier(cname, &mappedName);
+
+    GLuint progname = program->GLName();
+
+    MakeContextCurrent();
+    return gl->fGetUniformBlockIndex(progname, mappedName.get());
+}
+
+static bool
+GetUniformBlockActiveUniforms(gl::GLContext* gl, JSContext* cx,
+                              WebGL2Context* owner, GLuint progname,
+                              GLuint uniformBlockIndex,
+                              JS::MutableHandleObject out_array)
+{
+    GLint length = 0;
+    gl->fGetActiveUniformBlockiv(progname, uniformBlockIndex,
+                                 LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &length);
+    JS::RootedObject obj(cx, Uint32Array::Create(cx, owner, length, nullptr));
+    if (!obj)
+        return false;
+
+    JS::AutoCheckCannotGC nogc;
+    gl->fGetActiveUniformBlockiv(progname, uniformBlockIndex,
+                                 LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES,
+                                 (GLint*) JS_GetUint32ArrayData(obj, nogc));
+
+    out_array.set(obj);
+    return true;
 }
 
 void
-WebGL2Context::GetActiveUniformBlockParameter(JSContext*, WebGLProgram* program,
+WebGL2Context::GetActiveUniformBlockParameter(JSContext* cx, WebGLProgram* program,
                                               GLuint uniformBlockIndex, GLenum pname,
-                                              JS::MutableHandleValue retval)
+                                              Nullable<dom::OwningUnsignedLongOrUint32ArrayOrBoolean>& retval,
+                                              ErrorResult& rv)
 {
-    MOZ_CRASH("Not Implemented.");
+    retval.SetNull();
+    if (IsContextLost())
+        return;
+
+    if (!ValidateObject("getActiveUniformBlockParameter: program", program))
+        return;
+
+    GLuint progname = program->GLName();
+    GLint param = 0;
+    JS::RootedObject array(cx);
+
+    MakeContextCurrent();
+
+    switch(pname) {
+    case LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
+    case LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
+        gl->fGetActiveUniformBlockiv(progname, uniformBlockIndex, pname, &param);
+        retval.SetValue().SetAsBoolean() = (param != 0);
+        return;
+
+    case LOCAL_GL_UNIFORM_BLOCK_BINDING:
+    case LOCAL_GL_UNIFORM_BLOCK_DATA_SIZE:
+    case LOCAL_GL_UNIFORM_BLOCK_NAME_LENGTH:
+    case LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
+        gl->fGetActiveUniformBlockiv(progname, uniformBlockIndex, pname, &param);
+        retval.SetValue().SetAsUnsignedLong() = param;
+        return;
+
+    case LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
+        if (!GetUniformBlockActiveUniforms(gl, cx, this, progname, uniformBlockIndex,
+                                           &array))
+        {
+            rv = NS_ERROR_OUT_OF_MEMORY;
+            return;
+        }
+
+        DebugOnly<bool> inited = retval.SetValue().SetAsUint32Array().Init(array);
+        MOZ_ASSERT(inited);
+
+        return;
+    }
+
+    ErrorInvalidEnumInfo("getActiveUniformBlockParameter: parameter", pname);
 }
 
+#define WEBGL_MAX_UNIFORM_BLOCK_NAME_LENGTH 256
+
 void
-WebGL2Context::GetActiveUniformBlockName(WebGLProgram* program, GLuint uniformBlockIndex, dom::DOMString& retval)
+WebGL2Context::GetActiveUniformBlockName(WebGLProgram* program, GLuint uniformBlockIndex,
+                                         nsAString& retval)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (IsContextLost())
+        return;
+
+    if (!ValidateObject("getActiveUniformBlockName: program", program))
+        return;
+
+    GLuint progname = program->GLName();
+    GLchar nameBuffer[WEBGL_MAX_UNIFORM_BLOCK_NAME_LENGTH];
+    GLsizei length = 0;
+
+    MakeContextCurrent();
+    gl->fGetActiveUniformBlockName(progname, uniformBlockIndex,
+                                   WEBGL_MAX_UNIFORM_BLOCK_NAME_LENGTH, &length,
+                                   nameBuffer);
+    retval.Assign(NS_ConvertASCIItoUTF16(nsDependentCString(nameBuffer)));
 }
 
+#undef WEBGL_MAX_UNIFORM_BLOCK_NAME_LENGTH
+
 void
-WebGL2Context::UniformBlockBinding(WebGLProgram* program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
+WebGL2Context::UniformBlockBinding(WebGLProgram* program, GLuint uniformBlockIndex,
+                                   GLuint uniformBlockBinding)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (IsContextLost())
+        return;
+
+    if (!ValidateObject("uniformBlockBinding: program", program))
+        return;
+
+    GLuint progname = program->GLName();
+
+    MakeContextCurrent();
+    gl->fUniformBlockBinding(progname, uniformBlockIndex, uniformBlockBinding);
 }
--- a/dom/webidl/WebGL2RenderingContext.webidl
+++ b/dom/webidl/WebGL2RenderingContext.webidl
@@ -449,21 +449,25 @@ interface WebGL2RenderingContext : WebGL
     void transformFeedbackVaryings(WebGLProgram? program, sequence<DOMString> varyings, GLenum bufferMode);
     [NewObject] WebGLActiveInfo? getTransformFeedbackVarying(WebGLProgram? program, GLuint index);
     void pauseTransformFeedback();
     void resumeTransformFeedback();
 
     /* 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);
-    any getIndexedParameter(GLenum target, GLuint index);
+    // 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);
     GLuint getUniformBlockIndex(WebGLProgram? program, DOMString uniformBlockName);
-    any getActiveUniformBlockParameter(WebGLProgram? program, GLuint uniformBlockIndex, GLenum pname);
+    [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();
     void deleteVertexArray(WebGLVertexArrayObject? vertexArray);
     [WebGLHandlesContextLoss] GLboolean isVertexArray(WebGLVertexArrayObject? vertexArray);