Bug 1048747 - [WebGL2] Implement uniform block/buffer. r=jgilbert, r=smaug
authorDan Glastonbury <dglastonbury@mozilla.com>
Tue, 16 Dec 2014 15:20:15 +1000
changeset 235064 dfb46363d636325d38b85fe811224084724d8fcc
parent 235063 64e991d62eeb23a9d283dcf0ce25e174658ced4d
child 235065 cdefc124ccaa705e08b8cab905a01e760302876d
push idunknown
push userunknown
push dateunknown
reviewersjgilbert, smaug
bugs1048747
milestone37.0a1
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,253 @@ 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;
+
+    Uint32Array result;
+    DebugOnly<bool> inited = result.Init(obj);
+    MOZ_ASSERT(inited);
+    result.ComputeLengthAndData();
+    gl->fGetActiveUniformBlockiv(progname, uniformBlockIndex,
+                                 LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES,
+                                 (GLint*) result.Data());
+
+    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;
+
+    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:
+        JS::RootedObject array(cx);
+        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);