Bug 1048720 - [WebGL2] Implement WebGL2Sampler. r=jgilbert
authorDan Glastonbury <dglastonbury@mozilla.com>
Mon, 27 Oct 2014 09:40:37 +1000
changeset 216189 f8a4c88911b71c748f917c5c98122d9eae08de24
parent 216188 465b7f68072becf42240a386823eb8cdd6cebc9c
child 216190 5ee39194ac67afe32c52a5452e3ab017c887f11e
push id27842
push usercbook@mozilla.com
push dateTue, 18 Nov 2014 16:25:55 +0000
treeherdermozilla-central@084441e904d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert
bugs1048720
milestone36.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 1048720 - [WebGL2] Implement WebGL2Sampler. r=jgilbert
dom/canvas/WebGL2ContextSamplers.cpp
dom/canvas/WebGLContext.cpp
dom/canvas/WebGLContext.h
dom/canvas/WebGLContextUnchecked.cpp
dom/canvas/WebGLContextUnchecked.h
dom/canvas/WebGLContextValidate.cpp
dom/canvas/WebGLFramebuffer.cpp
dom/canvas/WebGLSampler.cpp
dom/canvas/WebGLSampler.h
dom/canvas/moz.build
--- a/dom/canvas/WebGL2ContextSamplers.cpp
+++ b/dom/canvas/WebGL2ContextSamplers.cpp
@@ -1,78 +1,218 @@
 /* -*- 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 "WebGLSampler.h"
 #include "GLContext.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 already_AddRefed<WebGLSampler>
 WebGL2Context::CreateSampler()
 {
-    MOZ_CRASH("Not Implemented.");
-    return nullptr;
+    if (IsContextLost())
+        return nullptr;
+
+    GLuint sampler;
+    MakeContextCurrent();
+    gl->fGenSamplers(1, &sampler);
+
+    nsRefPtr<WebGLSampler> globj = new WebGLSampler(this, sampler);
+    return globj.forget();
 }
 
 void
 WebGL2Context::DeleteSampler(WebGLSampler* sampler)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (IsContextLost())
+        return;
+
+    if (!ValidateObjectAllowDeletedOrNull("deleteSampler", sampler))
+        return;
+
+    if (!sampler || sampler->IsDeleted())
+        return;
+
+    sampler->RequestDelete();
 }
 
 bool
 WebGL2Context::IsSampler(WebGLSampler* sampler)
 {
-    MOZ_CRASH("Not Implemented.");
-    return false;
+    if (IsContextLost())
+        return false;
+
+    if (!sampler)
+        return false;
+
+    if (!ValidateObjectAllowDeleted("isSampler", sampler))
+        return false;
+
+    if (sampler->IsDeleted())
+        return false;
+
+    return !sampler->HasEverBeenBound();
 }
 
 void
 WebGL2Context::BindSampler(GLuint unit, WebGLSampler* sampler)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (IsContextLost())
+        return;
+
+    if (!ValidateObjectAllowDeletedOrNull("bindSampler", sampler))
+        return;
+
+    if (GLint(unit) >= mGLMaxTextureUnits)
+        return ErrorInvalidValue("bindSampler: unit must be < %d", mGLMaxTextureUnits);
+
+    if (sampler && sampler->IsDeleted())
+        return ErrorInvalidOperation("bindSampler: binding deleted sampler");
+
+    WebGLContextUnchecked::BindSampler(unit, sampler);
 }
 
 void
 WebGL2Context::SamplerParameteri(WebGLSampler* sampler, GLenum pname, GLint param)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (IsContextLost())
+        return;
+
+    if (!sampler || sampler->IsDeleted())
+        return ErrorInvalidOperation("samplerParameteri: invalid sampler");
+
+    if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param), "samplerParameteri"))
+        return;
+
+    WebGLContextUnchecked::SamplerParameteri(sampler, pname, param);
 }
 
 void
 WebGL2Context::SamplerParameteriv(WebGLSampler* sampler, GLenum pname, const dom::Int32Array& param)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (IsContextLost())
+        return;
+
+    if (!sampler || sampler->IsDeleted())
+        return ErrorInvalidOperation("samplerParameteriv: invalid sampler");
+
+    param.ComputeLengthAndData();
+    if (param.Length() < 1)
+        return /* TODO(djg): Error message */;
+
+    /* TODO(djg): All of these calls in ES3 only take 1 param */
+    if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param.Data()[0]), "samplerParameteriv"))
+        return;
+
+    WebGLContextUnchecked::SamplerParameteriv(sampler, pname, param.Data());
 }
 
 void
 WebGL2Context::SamplerParameteriv(WebGLSampler* sampler, GLenum pname, const dom::Sequence<GLint>& param)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (IsContextLost())
+        return;
+
+    if (!sampler || sampler->IsDeleted())
+        return ErrorInvalidOperation("samplerParameteriv: invalid sampler");
+
+    if (param.Length() < 1)
+        return /* TODO(djg): Error message */;
+
+    /* TODO(djg): All of these calls in ES3 only take 1 param */
+    if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param[0]), "samplerParameteriv"))
+        return;
+
+    WebGLContextUnchecked::SamplerParameteriv(sampler, pname, param.Elements());
 }
 
 void
 WebGL2Context::SamplerParameterf(WebGLSampler* sampler, GLenum pname, GLfloat param)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (IsContextLost())
+        return;
+
+    if (!sampler || sampler->IsDeleted())
+        return ErrorInvalidOperation("samplerParameterf: invalid sampler");
+
+    if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param), "samplerParameterf"))
+        return;
+
+    WebGLContextUnchecked::SamplerParameterf(sampler, pname, param);
 }
 
 void
 WebGL2Context::SamplerParameterfv(WebGLSampler* sampler, GLenum pname, const dom::Float32Array& param)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (IsContextLost())
+        return;
+
+    if (!sampler || sampler->IsDeleted())
+        return ErrorInvalidOperation("samplerParameterfv: invalid sampler");
+
+    param.ComputeLengthAndData();
+    if (param.Length() < 1)
+        return /* TODO(djg): Error message */;
+
+    /* TODO(djg): All of these calls in ES3 only take 1 param */
+    if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param.Data()[0]), "samplerParameterfv"))
+        return;
+
+    WebGLContextUnchecked::SamplerParameterfv(sampler, pname, param.Data());
 }
 
 void
 WebGL2Context::SamplerParameterfv(WebGLSampler* sampler, GLenum pname, const dom::Sequence<GLfloat>& param)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (IsContextLost())
+        return;
+
+    if (!sampler || sampler->IsDeleted())
+        return ErrorInvalidOperation("samplerParameterfv: invalid sampler");
+
+    if (param.Length() < 1)
+        return /* TODO(djg): Error message */;
+
+    /* TODO(djg): All of these calls in ES3 only take 1 param */
+    if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param[0]), "samplerParameterfv"))
+        return;
+
+    WebGLContextUnchecked::SamplerParameterfv(sampler, pname, param.Elements());
 }
 
 void
 WebGL2Context::GetSamplerParameter(JSContext*, WebGLSampler* sampler, GLenum pname, JS::MutableHandleValue retval)
 {
-    MOZ_CRASH("Not Implemented.");
+    if (IsContextLost())
+        return;
+
+    if (!sampler || sampler->IsDeleted())
+        return ErrorInvalidOperation("getSamplerParameter: invalid sampler");
+
+    if (!ValidateSamplerParameterName(pname, "getSamplerParameter"))
+        return;
+
+    retval.set(JS::NullValue());
+
+    switch (pname) {
+    case LOCAL_GL_TEXTURE_MIN_FILTER:
+    case LOCAL_GL_TEXTURE_MAG_FILTER:
+    case LOCAL_GL_TEXTURE_WRAP_S:
+    case LOCAL_GL_TEXTURE_WRAP_T:
+    case LOCAL_GL_TEXTURE_WRAP_R:
+    case LOCAL_GL_TEXTURE_COMPARE_MODE:
+    case LOCAL_GL_TEXTURE_COMPARE_FUNC:
+        retval.set(JS::Int32Value(
+            WebGLContextUnchecked::GetSamplerParameteriv(sampler, pname)));
+        return;
+
+    case LOCAL_GL_TEXTURE_MIN_LOD:
+    case LOCAL_GL_TEXTURE_MAX_LOD:
+        retval.set(JS::Float32Value(
+            WebGLContextUnchecked::GetSamplerParameterfv(sampler, pname)));
+        return;
+    }
 }
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -2,25 +2,26 @@
 /* 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 "WebGLContext.h"
 
 #include "WebGLContextLossHandler.h"
 #include "WebGL1Context.h"
-#include "WebGLObjectModel.h"
+#include "WebGLBuffer.h"
+#include "WebGLContextUtils.h"
 #include "WebGLExtensions.h"
-#include "WebGLContextUtils.h"
-#include "WebGLBuffer.h"
+#include "WebGLFramebuffer.h"
+#include "WebGLMemoryTracker.h"
+#include "WebGLObjectModel.h"
+#include "WebGLQuery.h"
+#include "WebGLSampler.h"
+#include "WebGLVertexArray.h"
 #include "WebGLVertexAttribData.h"
-#include "WebGLMemoryTracker.h"
-#include "WebGLFramebuffer.h"
-#include "WebGLVertexArray.h"
-#include "WebGLQuery.h"
 
 #include "GLBlitHelper.h"
 #include "AccessCheck.h"
 #include "nsIConsoleService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIClassInfoImpl.h"
 #include "nsContentUtils.h"
 #include "nsIXPConnect.h"
@@ -221,17 +222,17 @@ WebGLContextOptions::WebGLContextOptions
       preserveDrawingBuffer(false)
 {
     // Set default alpha state based on preference.
     if (Preferences::GetBool("webgl.default-no-alpha", false))
         alpha = false;
 }
 
 WebGLContext::WebGLContext()
-    : gl(nullptr)
+    : WebGLContextUnchecked(nullptr)
     , mNeedsFakeNoAlpha(false)
 {
     mGeneration = 0;
     mInvalidated = false;
     mShouldPresent = true;
     mResetLayer = true;
     mOptionsFrozen = false;
 
@@ -366,16 +367,18 @@ WebGLContext::DestroyResourcesAndContext
     while (!mFramebuffers.isEmpty())
         mFramebuffers.getLast()->DeleteOnce();
     while (!mShaders.isEmpty())
         mShaders.getLast()->DeleteOnce();
     while (!mPrograms.isEmpty())
         mPrograms.getLast()->DeleteOnce();
     while (!mQueries.isEmpty())
         mQueries.getLast()->DeleteOnce();
+    while (!mSamplers.isEmpty())
+        mSamplers.getLast()->DeleteOnce();
 
     mBlackOpaqueTexture2D = nullptr;
     mBlackOpaqueTextureCubeMap = nullptr;
     mBlackTransparentTexture2D = nullptr;
     mBlackTransparentTextureCubeMap = nullptr;
 
     if (mFakeVertexAttrib0BufferObject) {
         gl->fDeleteBuffers(1, &mFakeVertexAttrib0BufferObject);
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -10,16 +10,17 @@
 #include "mozilla/CheckedInt.h"
 #include "mozilla/EnumeratedArray.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/WeakPtr.h"
 
 #include "GLDefs.h"
 #include "WebGLActiveInfo.h"
+#include "WebGLContextUnchecked.h"
 #include "WebGLObjectModel.h"
 #include "WebGLRenderbuffer.h"
 #include "WebGLTexture.h"
 #include "WebGLStrongTypes.h"
 #include <stdarg.h>
 
 #include "nsTArray.h"
 #include "nsCycleCollectionNoteChild.h"
@@ -73,20 +74,22 @@ class WebGLExtensionBase;
 class WebGLBuffer;
 struct WebGLVertexAttribData;
 class WebGLShader;
 class WebGLProgram;
 class WebGLQuery;
 class WebGLUniformLocation;
 class WebGLFramebuffer;
 class WebGLRenderbuffer;
+class WebGLSampler;
 class WebGLShaderPrecisionFormat;
 class WebGLTexture;
 class WebGLVertexArray;
 
+
 namespace dom {
 class ImageData;
 class Element;
 
 struct WebGLContextAttributes;
 template<typename> struct Nullable;
 }
 
@@ -122,20 +125,39 @@ struct WebGLContextOptions {
     bool premultipliedAlpha;
     bool antialias;
     bool preserveDrawingBuffer;
 };
 
 // From WebGLContextUtils
 TexTarget TexImageTargetToTexTarget(TexImageTarget texImageTarget);
 
+class WebGLIntOrFloat {
+    enum {
+        Int,
+        Float
+    } mType;
+    union {
+        GLint i;
+        GLfloat f;
+    } mValue;
+
+public:
+    explicit WebGLIntOrFloat(GLint i) : mType(Int) { mValue.i = i; }
+    explicit WebGLIntOrFloat(GLfloat f) : mType(Float) { mValue.f = f; }
+
+    GLint AsInt() const { return (mType == Int) ? mValue.i : NS_lroundf(mValue.f); }
+    GLfloat AsFloat() const { return (mType == Float) ? mValue.f : GLfloat(mValue.i); }
+};
+
 class WebGLContext :
     public nsIDOMWebGLRenderingContext,
     public nsICanvasRenderingContextInternal,
     public nsSupportsWeakReference,
+    public WebGLContextUnchecked,
     public WebGLRectangleObject,
     public nsWrapperCache,
     public SupportsWeakPtr<WebGLContext>
 {
     friend class WebGLContextUserData;
     friend class WebGLExtensionCompressedTextureATC;
     friend class WebGLExtensionCompressedTextureETC1;
     friend class WebGLExtensionCompressedTexturePVRTC;
@@ -1000,18 +1022,16 @@ protected:
 
     virtual JS::Value GetTexParameterInternal(const TexTarget& target, GLenum pname);
 
     // Returns x rounded to the next highest multiple of y.
     static CheckedUint32 RoundedToNextMultipleOf(CheckedUint32 x, CheckedUint32 y) {
         return ((x + y - 1) / y) * y;
     }
 
-    nsRefPtr<gl::GLContext> gl;
-
     CheckedUint32 mGeneration;
 
     WebGLContextOptions mOptions;
 
     bool mInvalidated;
     bool mResetLayer;
     bool mOptionsFrozen;
     bool mMinCapability;
@@ -1133,16 +1153,20 @@ protected:
 
     bool ValidateGLSLVariableName(const nsAString& name, const char *info);
     bool ValidateGLSLCharacter(char16_t c);
     bool ValidateGLSLString(const nsAString& string, const char *info);
 
     bool ValidateCopyTexImage(GLenum internalformat,
                               WebGLTexImageFunc func,
                               WebGLTexDimensions dims);
+
+    bool ValidateSamplerParameterName(GLenum pname, const char* info);
+    bool ValidateSamplerParameterParams(GLenum pname, const WebGLIntOrFloat& param, const char* info);
+
     bool ValidateTexImage(TexImageTarget texImageTarget,
                           GLint level, GLenum internalFormat,
                           GLint xoffset, GLint yoffset, GLint zoffset,
                           GLint width, GLint height, GLint depth,
                           GLint border, GLenum format, GLenum type,
                           WebGLTexImageFunc func,
                           WebGLTexDimensions dims);
     bool ValidateTexImageTarget(GLenum target,
@@ -1320,16 +1344,19 @@ protected:
     LinkedList<WebGLBuffer> mBuffers;
     LinkedList<WebGLProgram> mPrograms;
     LinkedList<WebGLQuery> mQueries;
     LinkedList<WebGLShader> mShaders;
     LinkedList<WebGLRenderbuffer> mRenderbuffers;
     LinkedList<WebGLFramebuffer> mFramebuffers;
     LinkedList<WebGLVertexArray> mVertexArrays;
 
+    // TODO(djg): Does this need a rethink? Should it be WebGL2Context?
+    LinkedList<WebGLSampler> mSamplers;
+
     WebGLRefPtr<WebGLVertexArray> mDefaultVertexArray;
 
     // PixelStore parameters
     uint32_t mPixelStorePackAlignment, mPixelStoreUnpackAlignment, mPixelStoreColorspaceConversion;
     bool mPixelStoreFlipY, mPixelStorePremultiplyAlpha;
 
     WebGLContextFakeBlackStatus mFakeBlackStatus;
 
@@ -1435,16 +1462,17 @@ public:
     void GenerateWarning(const char *fmt, va_list ap);
 
     friend class WebGLTexture;
     friend class WebGLFramebuffer;
     friend class WebGLRenderbuffer;
     friend class WebGLProgram;
     friend class WebGLQuery;
     friend class WebGLBuffer;
+    friend class WebGLSampler;
     friend class WebGLShader;
     friend class WebGLUniformLocation;
     friend class WebGLVertexArray;
     friend class WebGLVertexArrayFake;
     friend class WebGLVertexArrayGL;
 };
 
 // used by DOM bindings in conjunction with GetParentObject
new file mode 100644
--- /dev/null
+++ b/dom/canvas/WebGLContextUnchecked.cpp
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=4 et sw=4 tw=80: */
+/* 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 "WebGLContextUnchecked.h"
+
+#include "GLContext.h"
+#include "WebGLSampler.h"
+
+namespace mozilla {
+
+WebGLContextUnchecked::WebGLContextUnchecked(gl::GLContext* gl)
+    : gl(gl)
+{ }
+
+
+// -----------------------------------------------------------------------------
+// Sampler Objects
+
+void
+WebGLContextUnchecked::BindSampler(GLuint unit, WebGLSampler* sampler)
+{
+    gl->MakeCurrent();
+    gl->fBindSampler(unit, sampler ? sampler->GLName() : 0);
+    if (sampler)
+        sampler->BindTo(LOCAL_GL_SAMPLER_BINDING);
+}
+
+GLint
+WebGLContextUnchecked::GetSamplerParameteriv(WebGLSampler* sampler,
+                                             GLenum pname)
+{
+    MOZ_ASSERT(sampler, "Did you validate?");
+
+    GLint param = 0;
+    gl->MakeCurrent();
+    gl->fGetSamplerParameteriv(sampler->GLName(), pname, &param);
+
+    return param;
+}
+
+GLfloat
+WebGLContextUnchecked::GetSamplerParameterfv(WebGLSampler* sampler,
+                                             GLenum pname)
+{
+    MOZ_ASSERT(sampler, "Did you validate?");
+
+    GLfloat param = 0.0f;
+    gl->MakeCurrent();
+    gl->fGetSamplerParameterfv(sampler->GLName(), pname, &param);
+    return param;
+}
+
+void
+WebGLContextUnchecked::SamplerParameteri(WebGLSampler* sampler,
+                                         GLenum pname,
+                                         GLint param)
+{
+    MOZ_ASSERT(sampler, "Did you validate?");
+    gl->MakeCurrent();
+    gl->fSamplerParameteri(sampler->GLName(), pname, param);
+}
+
+void
+WebGLContextUnchecked::SamplerParameteriv(WebGLSampler* sampler,
+                                          GLenum pname,
+                                          const GLint* param)
+{
+    MOZ_ASSERT(sampler, "Did you validate?");
+    gl->MakeCurrent();
+    gl->fSamplerParameteriv(sampler->GLName(), pname, param);
+}
+
+void
+WebGLContextUnchecked::SamplerParameterf(WebGLSampler* sampler,
+                                         GLenum pname,
+                                         GLfloat param)
+{
+    MOZ_ASSERT(sampler, "Did you validate?");
+    gl->MakeCurrent();
+    gl->fSamplerParameterf(sampler->GLName(), pname, param);
+}
+
+void
+WebGLContextUnchecked::SamplerParameterfv(WebGLSampler* sampler,
+                                          GLenum pname,
+                                          const GLfloat* param)
+{
+    MOZ_ASSERT(sampler, "Did you validate?");
+    gl->MakeCurrent();
+    gl->fSamplerParameterfv(sampler->GLName(), pname, param);
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/canvas/WebGLContextUnchecked.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=4 et sw=4 tw=80: */
+/* 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/. */
+
+#ifndef WEBGLCONTEXTUNCHECKED_H
+#define WEBGLCONTEXTUNCHECKED_H
+
+#include "GLDefs.h"
+#include "WebGLTypes.h"
+#include "nsAutoPtr.h"
+#include "nsTArray.h"
+
+namespace mozilla {
+
+class WebGLSampler;
+namespace gl {
+    class GLContext;
+}
+
+class WebGLContextUnchecked
+{
+public:
+    explicit WebGLContextUnchecked(gl::GLContext* gl);
+
+    // -------------------------------------------------------------------------
+    // Sampler Objects
+    void BindSampler(GLuint unit, WebGLSampler* sampler);
+
+    GLint   GetSamplerParameteriv(WebGLSampler* sampler, GLenum pname);
+    GLfloat GetSamplerParameterfv(WebGLSampler* sampler, GLenum pname);
+
+    void SamplerParameteri(WebGLSampler* sampler, GLenum pname, GLint param);
+    void SamplerParameteriv(WebGLSampler* sampler, GLenum pname, const GLint* param);
+    void SamplerParameterf(WebGLSampler* sampler, GLenum pname, GLfloat param);
+    void SamplerParameterfv(WebGLSampler* sampler, GLenum pname, const GLfloat* param);
+
+protected: // data
+    nsRefPtr<gl::GLContext> gl;
+};
+
+} // namespace mozilla
+
+#endif // !WEBGLCONTEXTUNCHECKED_H
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -374,16 +374,128 @@ WebGLContext::ValidateFramebufferAttachm
         return true;
     }
 
     ErrorInvalidEnum("%s: attachment: invalid enum value 0x%x.", funcName, attachment);
     return false;
 }
 
 /**
+ * Return true if pname is valid for GetSamplerParameter calls.
+ */
+bool
+WebGLContext::ValidateSamplerParameterName(GLenum pname, const char* info)
+{
+    switch (pname) {
+    case LOCAL_GL_TEXTURE_MIN_FILTER:
+    case LOCAL_GL_TEXTURE_MAG_FILTER:
+    case LOCAL_GL_TEXTURE_WRAP_S:
+    case LOCAL_GL_TEXTURE_WRAP_T:
+    case LOCAL_GL_TEXTURE_WRAP_R:
+    case LOCAL_GL_TEXTURE_MIN_LOD:
+    case LOCAL_GL_TEXTURE_MAX_LOD:
+    case LOCAL_GL_TEXTURE_COMPARE_MODE:
+    case LOCAL_GL_TEXTURE_COMPARE_FUNC:
+        return true;
+
+    default:
+        ErrorInvalidEnum("%s: invalid pname: %s", info, EnumName(pname));
+        return false;
+    }
+}
+
+/**
+ * Return true if pname and param are valid combination for SamplerParameter calls.
+ */
+bool
+WebGLContext::ValidateSamplerParameterParams(GLenum pname, const WebGLIntOrFloat& param, const char* info)
+{
+    const GLenum p = param.AsInt();
+
+    switch (pname) {
+    case LOCAL_GL_TEXTURE_MIN_FILTER:
+        switch (p) {
+        case LOCAL_GL_NEAREST:
+        case LOCAL_GL_LINEAR:
+        case LOCAL_GL_NEAREST_MIPMAP_NEAREST:
+        case LOCAL_GL_NEAREST_MIPMAP_LINEAR:
+        case LOCAL_GL_LINEAR_MIPMAP_NEAREST:
+        case LOCAL_GL_LINEAR_MIPMAP_LINEAR:
+            return true;
+
+        default:
+            ErrorInvalidEnum("%s: invalid param: %s", info, EnumName(p));
+            return false;
+        }
+
+    case LOCAL_GL_TEXTURE_MAG_FILTER:
+        switch (p) {
+        case LOCAL_GL_NEAREST:
+        case LOCAL_GL_LINEAR:
+            return true;
+
+        default:
+            ErrorInvalidEnum("%s: invalid param: %s", info, EnumName(p));
+            return false;
+        }
+
+    case LOCAL_GL_TEXTURE_WRAP_S:
+    case LOCAL_GL_TEXTURE_WRAP_T:
+    case LOCAL_GL_TEXTURE_WRAP_R:
+        switch (p) {
+        case LOCAL_GL_CLAMP_TO_EDGE:
+        case LOCAL_GL_REPEAT:
+        case LOCAL_GL_MIRRORED_REPEAT:
+            return true;
+
+        default:
+            ErrorInvalidEnum("%s: invalid param: %s", info, EnumName(p));
+            return false;
+        }
+
+    case LOCAL_GL_TEXTURE_MIN_LOD:
+    case LOCAL_GL_TEXTURE_MAX_LOD:
+        return true;
+
+    case LOCAL_GL_TEXTURE_COMPARE_MODE:
+        switch (param.AsInt()) {
+        case LOCAL_GL_NONE:
+        case LOCAL_GL_COMPARE_REF_TO_TEXTURE:
+            return true;
+
+        default:
+            ErrorInvalidEnum("%s: invalid param: %s", info, EnumName(p));
+            return false;
+        }
+
+    case LOCAL_GL_TEXTURE_COMPARE_FUNC:
+        switch (p) {
+        case LOCAL_GL_LEQUAL:
+        case LOCAL_GL_GEQUAL:
+        case LOCAL_GL_LESS:
+        case LOCAL_GL_GREATER:
+        case LOCAL_GL_EQUAL:
+        case LOCAL_GL_NOTEQUAL:
+        case LOCAL_GL_ALWAYS:
+        case LOCAL_GL_NEVER:
+            return true;
+
+        default:
+            ErrorInvalidEnum("%s: invalid param: %s", info, EnumName(p));
+            return false;
+        }
+
+    default:
+        ErrorInvalidEnum("%s: invalid pname: %s", info, EnumName(pname));
+        return false;
+    }
+}
+
+
+/**
  * Return true if format is a valid texture image format for source,
  * taking into account enabled WebGL extensions.
  */
 bool
 WebGLContext::ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func, WebGLTexDimensions dims)
 {
     /* Core WebGL texture formats */
     if (format == LOCAL_GL_ALPHA ||
--- a/dom/canvas/WebGLFramebuffer.cpp
+++ b/dom/canvas/WebGLFramebuffer.cpp
@@ -368,17 +368,17 @@ WebGLFramebuffer::Attachment::FinalizeAt
                                          LOCAL_GL_RENDERBUFFER, 0);
         }
 
         return;
     }
     MOZ_ASSERT(HasImage());
 
     if (Texture()) {
-        MOZ_ASSERT(gl == Texture()->Context()->gl);
+        MOZ_ASSERT(gl == Texture()->Context()->GL());
 
         const GLenum imageTarget = ImageTarget().get();
         const GLint mipLevel = MipLevel();
         const GLuint glName = Texture()->GLName();
 
         if (attachmentLoc == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
             gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
                                       imageTarget, glName, mipLevel);
--- a/dom/canvas/WebGLSampler.cpp
+++ b/dom/canvas/WebGLSampler.cpp
@@ -7,42 +7,45 @@
 #include "WebGLSampler.h"
 
 #include "GLContext.h"
 
 #include "mozilla/dom/WebGL2RenderingContextBinding.h"
 
 using namespace mozilla;
 
-WebGLSampler::WebGLSampler(WebGLContext* context)
-    : WebGLBindableName<GLenum>(0),
+WebGLSampler::WebGLSampler(WebGLContext* context, GLuint sampler)
+    : WebGLBindableName<GLenum>(sampler),
       WebGLContextBoundObject(context)
 {
-    MOZ_CRASH("Not Implemented.");
+    mContext->mSamplers.insertBack(this);
 }
 
 WebGLSampler::~WebGLSampler()
-{}
+{
+    DeleteOnce();
+}
 
 void
 WebGLSampler::Delete()
 {
-    MOZ_CRASH("Not Implemented.");
+    mContext->MakeContextCurrent();
+    mContext->gl->fDeleteSamplers(1, &mGLName);
+
+    removeFrom(mContext->mSamplers);
 }
 
 WebGLContext*
 WebGLSampler::GetParentObject() const
 {
-    MOZ_CRASH("Not Implemented.");
-    return nullptr;
+    return Context();
 }
 
 JSObject*
 WebGLSampler::WrapObject(JSContext* cx)
 {
-    MOZ_CRASH("Not Implemented.");
     return dom::WebGLSamplerBinding::Wrap(cx, this);
 }
 
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLSampler)
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLSampler, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLSampler, Release)
--- a/dom/canvas/WebGLSampler.h
+++ b/dom/canvas/WebGLSampler.h
@@ -1,15 +1,15 @@
 /* -*- 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/. */
 
-#ifndef WEBGL2SAMPLER_H_
-#define WEBGL2SAMPLER_H_
+#ifndef WEBGLSAMPLER_H_
+#define WEBGLSAMPLER_H_
 
 #include "WebGLBindableName.h"
 #include "WebGLObjectModel.h"
 
 #include "nsWrapperCache.h"
 
 #include "mozilla/LinkedList.h"
 
@@ -21,26 +21,28 @@ class WebGLSampler MOZ_FINAL
     , public WebGLRefCountedObject<WebGLSampler>
     , public LinkedListElement<WebGLSampler>
     , public WebGLContextBoundObject
 {
     friend class WebGLContext2;
 
 public:
 
-    explicit WebGLSampler(WebGLContext* aContext);
+    explicit WebGLSampler(WebGLContext* aContext, GLuint sampler);
 
     void Delete();
     WebGLContext* GetParentObject() const;
 
     virtual JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE;
 
+private:
+
     NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLSampler)
     NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLSampler)
 
 private:
 
     ~WebGLSampler();
 };
 
 } // namespace mozilla
 
-#endif // !WEBGL2SAMPLER_H_
+#endif // !WEBGLSAMPLER_H_
--- a/dom/canvas/moz.build
+++ b/dom/canvas/moz.build
@@ -59,16 +59,17 @@ UNIFIED_SOURCES += [
     'WebGLContextBuffers.cpp',
     'WebGLContextDraw.cpp',
     'WebGLContextExtensions.cpp',
     'WebGLContextFramebufferOperations.cpp',
     'WebGLContextGL.cpp',
     'WebGLContextLossHandler.cpp',
     'WebGLContextReporter.cpp',
     'WebGLContextState.cpp',
+    'WebGLContextUnchecked.cpp',
     'WebGLContextUtils.cpp',
     'WebGLContextValidate.cpp',
     'WebGLContextVertexArray.cpp',
     'WebGLContextVertices.cpp',
     'WebGLElementArrayCache.cpp',
     'WebGLExtensionBase.cpp',
     'WebGLExtensionBlendMinMax.cpp',
     'WebGLExtensionColorBufferFloat.cpp',