Bug 1048719 - [WebGL2] Query objects. r=jgilbert
authorDan Glastonbury <dglastonbury@mozilla.com>
Mon, 03 Nov 2014 15:35:04 +1000
changeset 231916 e5bccb2e00cbe1e07934712b7850389dd874265b
parent 231914 f7705f553b85bc361857c72300bc279421cf9aa5
child 231917 13aa9ac1791ea6a8a3b649d7920245589b28d286
push idunknown
push userunknown
push dateunknown
reviewersjgilbert
bugs1048719
milestone36.0a1
Bug 1048719 - [WebGL2] Query objects. r=jgilbert
dom/canvas/WebGL2Context.h
dom/canvas/WebGL2ContextQueries.cpp
dom/canvas/WebGLContext.h
dom/canvas/WebGLContextAsyncQueries.cpp
dom/canvas/WebGLQuery.cpp
dom/canvas/WebGLQuery.h
dom/canvas/moz.build
--- a/dom/canvas/WebGL2Context.h
+++ b/dom/canvas/WebGL2Context.h
@@ -159,27 +159,29 @@ public:
     void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const dom::Uint32Array& value);
     void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const dom::Sequence<GLuint>& value);
     void ClearBufferfv(GLenum buffer, GLint drawbuffer, const dom::Float32Array& value);
     void ClearBufferfv(GLenum buffer, GLint drawbuffer, const dom::Sequence<GLfloat>& value);
     void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
 
     bool ValidateClearBuffer(const char* info, GLenum buffer, GLint drawbuffer, size_t elemCount);
 
+
     // -------------------------------------------------------------------------
     // Query Objects - WebGL2ContextQueries.cpp
-    // TODO(djg): Implemented in WebGLContext
-    /* already_AddRefed<WebGLQuery> CreateQuery();
+
+    already_AddRefed<WebGLQuery> CreateQuery();
     void DeleteQuery(WebGLQuery* query);
     bool IsQuery(WebGLQuery* query);
     void BeginQuery(GLenum target, WebGLQuery* query);
     void EndQuery(GLenum target);
-    JS::Value GetQuery(JSContext*, GLenum target, GLenum pname); */
+    already_AddRefed<WebGLQuery> GetQuery(GLenum target, GLenum pname);
     void GetQueryParameter(JSContext*, WebGLQuery* query, GLenum pname, JS::MutableHandleValue retval);
 
+
     // -------------------------------------------------------------------------
     // Sampler Objects - WebGL2ContextSamplers.cpp
 
     already_AddRefed<WebGLSampler> CreateSampler();
     void DeleteSampler(WebGLSampler* sampler);
     bool IsSampler(WebGLSampler* sampler);
     void BindSampler(GLuint unit, WebGLSampler* sampler);
     void SamplerParameteri(WebGLSampler* sampler, GLenum pname, GLint param);
@@ -199,16 +201,17 @@ public:
     void DeleteSync(WebGLSync* sync);
     GLenum ClientWaitSync(WebGLSync* sync, GLbitfield flags, GLuint64 timeout);
     void WaitSync(WebGLSync* sync, GLbitfield flags, GLuint64 timeout);
     void GetSyncParameter(JSContext*, WebGLSync* sync, GLenum pname, JS::MutableHandleValue retval);
 
 
     // -------------------------------------------------------------------------
     // Transform Feedback - WebGL2ContextTransformFeedback.cpp
+
     already_AddRefed<WebGLTransformFeedback> CreateTransformFeedback();
     void DeleteTransformFeedback(WebGLTransformFeedback* tf);
     bool IsTransformFeedback(WebGLTransformFeedback* tf);
     void BindTransformFeedback(GLenum target, GLuint id);
     void BeginTransformFeedback(GLenum primitiveMode);
     void EndTransformFeedback();
     void TransformFeedbackVaryings(WebGLProgram* program, GLsizei count,
                                    const dom::Sequence<nsString>& varyings, GLenum bufferMode);
@@ -240,17 +243,16 @@ public:
 /*
     already_AddRefed<WebGLVertexArrayObject> CreateVertexArray();
     void DeleteVertexArray(WebGLVertexArrayObject* vertexArray);
     bool IsVertexArray(WebGLVertexArrayObject* vertexArray);
     void BindVertexArray(WebGLVertexArrayObject* vertexArray);
 */
 
 private:
-
     WebGL2Context();
 
     bool ValidateSizedInternalFormat(GLenum internalFormat, const char* info);
     bool ValidateTexStorage(GLenum target, GLsizei levels, GLenum internalformat,
                                 GLsizei width, GLsizei height, GLsizei depth,
                                 const char* info);
     JS::Value GetTexParameterInternal(const TexTarget& target, GLenum pname) MOZ_OVERRIDE;
 };
--- a/dom/canvas/WebGL2ContextQueries.cpp
+++ b/dom/canvas/WebGL2ContextQueries.cpp
@@ -1,28 +1,353 @@
 /* -*- 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 "WebGLQuery.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
+/*
+ * We fake ANY_SAMPLES_PASSED and ANY_SAMPLES_PASSED_CONSERVATIVE with
+ * SAMPLES_PASSED on desktop.
+ *
+ * OpenGL ES 3.0 spec 4.1.6
+ *  If the target of the query is ANY_SAMPLES_PASSED_CONSERVATIVE, an
+ *  implementation may choose to use a less precise version of the test which
+ *  can additionally set the samples-boolean state to TRUE in some other
+ *  implementation-dependent cases.
+ */
+
+static const char*
+GetQueryTargetEnumString(GLenum target)
+{
+    switch (target)
+    {
+        case LOCAL_GL_ANY_SAMPLES_PASSED:
+            return "ANY_SAMPLES_PASSED";
+        case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+            return "ANY_SAMPLES_PASSED_CONSERVATIVE";
+        case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+            return "TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN";
+        default:
+            break;
+    }
+
+    MOZ_ASSERT(false, "Unknown query `target`.");
+    return "UNKNOWN_QUERY_TARGET";
+}
+
+static inline GLenum
+SimulateOcclusionQueryTarget(const gl::GLContext* gl, GLenum target)
+{
+    MOZ_ASSERT(target == LOCAL_GL_ANY_SAMPLES_PASSED ||
+               target == LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE,
+               "unknown occlusion query target");
+
+    if (gl->IsSupported(gl::GLFeature::occlusion_query_boolean)) {
+        return target;
+    } else if (gl->IsSupported(gl::GLFeature::occlusion_query2)) {
+        return LOCAL_GL_ANY_SAMPLES_PASSED;
+    }
+
+    return LOCAL_GL_SAMPLES_PASSED;
+}
+
+WebGLQueryRefPtr*
+WebGLContext::GetQueryTargetSlot(GLenum target)
+{
+    switch (target) {
+        case LOCAL_GL_ANY_SAMPLES_PASSED:
+        case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+            return &mActiveOcclusionQuery;
+
+        case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+            return &mActiveTransformFeedbackQuery;
+    }
+
+    return nullptr;
+}
+
+
 // -------------------------------------------------------------------------
 // Query Objects
-// TODO(djg): Implemented in WebGLContext
+
+already_AddRefed<WebGLQuery>
+WebGL2Context::CreateQuery()
+{
+    if (IsContextLost())
+        return nullptr;
+
+    if (mActiveOcclusionQuery && !gl->IsGLES()) {
+        /* http://www.opengl.org/registry/specs/ARB/occlusion_query.txt
+         *
+         * Calling either GenQueriesARB or DeleteQueriesARB while any query of
+         * any target is active causes an INVALID_OPERATION error to be
+         * generated.
+         */
+        GenerateWarning("createQuery: the WebGL 2 prototype might generate "
+                        "INVALID_OPERATION when creating a query object while "
+                        "one other is active.");
+        /*
+         * We *need* to lock webgl2 to GL>=3.0 on desktop, but we don't have a
+         * good mechanism to do this yet. See bug 898404.
+         */
+    }
+
+    nsRefPtr<WebGLQuery> globj = new WebGLQuery(this);
+
+    return globj.forget();
+}
+
+void
+WebGL2Context::DeleteQuery(WebGLQuery* query)
+{
+    if (IsContextLost())
+        return;
+
+    if (!query)
+        return;
+
+    if (query->IsDeleted())
+        return;
+
+    if (query->IsActive())
+        EndQuery(query->mType);
+
+    if (mActiveOcclusionQuery && !gl->IsGLES()) {
+        /* http://www.opengl.org/registry/specs/ARB/occlusion_query.txt
+         *
+         * Calling either GenQueriesARB or DeleteQueriesARB while any query of
+         * any target is active causes an INVALID_OPERATION error to be
+         * generated.
+         */
+        GenerateWarning("deleteQuery: the WebGL 2 prototype might generate "
+                        "INVALID_OPERATION when deleting a query object while "
+                        "one other is active.");
+    }
+
+    query->RequestDelete();
+}
+
+bool
+WebGL2Context::IsQuery(WebGLQuery* query)
+{
+    if (IsContextLost())
+        return false;
+
+    if (!query)
+        return false;
+
+    return (ValidateObjectAllowDeleted("isQuery", query) &&
+            !query->IsDeleted() &&
+            query->HasEverBeenActive());
+}
+
+void
+WebGL2Context::BeginQuery(GLenum target, WebGLQuery* query)
+{
+    if (IsContextLost())
+        return;
+
+    WebGLRefPtr<WebGLQuery>* targetSlot = GetQueryTargetSlot(target);
+    if (!targetSlot) {
+        ErrorInvalidEnum("beginQuery: unknown query target");
+        return;
+    }
+
+    if (!query) {
+        /* SPECS BeginQuery.1
+         * http://www.khronos.org/registry/gles/extensions/EXT/EXT_occlusion_query_boolean.txt
+         * BeginQueryEXT sets the active query object name for the query type given
+         * by <target> to <id>. If BeginQueryEXT is called with an <id> of zero, if
+         * the active query object name for <target> is non-zero (for the targets
+         * ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if the
+         * active query for either target is non-zero), if <id> is the name of an
+         * existing query object whose type does not match <target>, or if <id> is the
+         * active query object name for any query type, the error INVALID_OPERATION is
+         * generated.
+         */
+        ErrorInvalidOperation("beginQuery: query should not be null");
+        return;
+    }
 
-/*
-    already_AddRefed<WebGLQuery> CreateQuery();
-    void DeleteQuery(WebGLQuery* query);
-    bool IsQuery(WebGLQuery* query);
-    void BeginQuery(GLenum target, WebGLQuery* query);
-    void EndQuery(GLenum target);
-    JS::Value GetQuery(JSContext*, GLenum target, GLenum pname);
-*/
+    if (query->IsDeleted()) {
+        /* http://www.khronos.org/registry/gles/extensions/EXT/EXT_occlusion_query_boolean.txt
+         * BeginQueryEXT fails and an INVALID_OPERATION error is generated if <id>
+         * is not a name returned from a previous call to GenQueriesEXT, or if such
+         * a name has since been deleted with DeleteQueriesEXT.
+         */
+        ErrorInvalidOperation("beginQuery: query has been deleted");
+        return;
+    }
+
+    if (query->HasEverBeenActive() &&
+        query->mType != target)
+    {
+        /*
+         * See SPECS BeginQuery.1
+         */
+        ErrorInvalidOperation("beginQuery: target doesn't match with the query type");
+        return;
+    }
+
+    if (*targetSlot) {
+        /*
+         * See SPECS BeginQuery.1
+         */
+        ErrorInvalidOperation("beginQuery: an other query already active");
+        return;
+    }
+
+    if (!query->HasEverBeenActive()) {
+        query->mType = target;
+    }
+
+    MakeContextCurrent();
+
+    if (target == LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) {
+        gl->fBeginQuery(LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query->mGLName);
+    } else {
+        gl->fBeginQuery(SimulateOcclusionQueryTarget(gl, target), query->mGLName);
+    }
+
+    *targetSlot = query;
+}
+
+void
+WebGL2Context::EndQuery(GLenum target)
+{
+    if (IsContextLost())
+        return;
+
+    WebGLRefPtr<WebGLQuery>* targetSlot = GetQueryTargetSlot(target);
+    if (!targetSlot) {
+        ErrorInvalidEnum("endQuery: unknown query target");
+        return;
+    }
+
+    if (!*targetSlot || target != (*targetSlot)->mType) {
+        /* http://www.khronos.org/registry/gles/extensions/EXT/EXT_occlusion_query_boolean.txt
+         * marks the end of the sequence of commands to be tracked for the query type
+         * given by <target>. The active query object for <target> is updated to
+         * indicate that query results are not available, and the active query object
+         * name for <target> is reset to zero. When the commands issued prior to
+         * EndQueryEXT have completed and a final query result is available, the
+         * query object active when EndQueryEXT is called is updated by the GL. The
+         * query object is updated to indicate that the query results are available
+         * and to contain the query result. If the active query object name for
+         * <target> is zero when EndQueryEXT is called, the error INVALID_OPERATION
+         * is generated.
+         */
+        ErrorInvalidOperation("endQuery: There is no active query of type %s.",
+                              GetQueryTargetEnumString(target));
+        return;
+    }
+
+    MakeContextCurrent();
+
+    if (target == LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) {
+        gl->fEndQuery(LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
+    } else {
+        gl->fEndQuery(SimulateOcclusionQueryTarget(gl, target));
+    }
+
+    *targetSlot = nullptr;
+}
+
+already_AddRefed<WebGLQuery>
+WebGL2Context::GetQuery(GLenum target, GLenum pname)
+{
+    if (IsContextLost())
+        return nullptr;
+
+    WebGLRefPtr<WebGLQuery>* targetSlot = GetQueryTargetSlot(target);
+    if (!targetSlot) {
+        ErrorInvalidEnum("getQuery: unknown query target");
+        return nullptr;
+    }
+
+    if (pname != LOCAL_GL_CURRENT_QUERY) {
+        /* OpenGL ES 3.0 spec 6.1.7
+         *  pname must be CURRENT_QUERY.
+         */
+        ErrorInvalidEnum("getQuery: pname must be CURRENT_QUERY");
+        return nullptr;
+    }
+
+    nsRefPtr<WebGLQuery> tmp = targetSlot->get();
+    return tmp.forget();
+}
+
 void
 WebGL2Context::GetQueryParameter(JSContext*, WebGLQuery* query, GLenum pname, JS::MutableHandleValue retval)
 {
-    MOZ_CRASH("Not Implemented");
+    retval.set(JS::NullValue());
+
+    if (IsContextLost())
+        return;
+
+    if (!query) {
+        /* OpenGL ES 3.0 spec 6.1.7 (spec getQueryObject 1)
+         *  If id is not the name of a query object, or if the query object named by id is
+         *  currently active, then an INVALID_OPERATION error is generated. pname must be
+         *  QUERY_RESULT or QUERY_RESULT_AVAILABLE.
+         */
+        ErrorInvalidOperation("getQueryObject: query should not be null");
+        return;
+    }
+
+    if (query->IsDeleted()) {
+        // See (spec getQueryObject 1)
+        ErrorInvalidOperation("getQueryObject: query has been deleted");
+        return;
+    }
+
+    if (query->IsActive()) {
+        // See (spec getQueryObject 1)
+        ErrorInvalidOperation("getQueryObject: query is active");
+        return;
+    }
+
+    if (!query->HasEverBeenActive()) {
+        /* See (spec getQueryObject 1)
+         *  If this instance of WebGLQuery has never been active before, that mean that
+         *  query->mGLName is not a query object yet.
+         */
+        ErrorInvalidOperation("getQueryObject: query has never been active");
+        return;
+    }
+
+    MakeContextCurrent();
+    GLuint returned = 0;
+    switch (pname) {
+    case LOCAL_GL_QUERY_RESULT_AVAILABLE:
+        gl->fGetQueryObjectuiv(query->mGLName, LOCAL_GL_QUERY_RESULT_AVAILABLE, &returned);
+        retval.set(JS::BooleanValue(returned != 0));
+        return;
+
+    case LOCAL_GL_QUERY_RESULT:
+        gl->fGetQueryObjectuiv(query->mGLName, LOCAL_GL_QUERY_RESULT, &returned);
+
+        if (query->mType == LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) {
+            retval.set(JS::NumberValue(returned));
+            return;
+        }
+
+        /*
+         * test (returned != 0) is important because ARB_occlusion_query on desktop drivers
+         * return the number of samples drawed when the OpenGL ES extension
+         * ARB_occlusion_query_boolean return only a boolean if a sample has been drawed.
+         */
+        retval.set(JS::BooleanValue(returned != 0));
+        return;
+
+    default:
+        break;
+    }
+
+    ErrorInvalidEnum("getQueryObject: pname must be QUERY_RESULT{_AVAILABLE}");
 }
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -67,41 +67,42 @@ class nsIDocShell;
 namespace mozilla {
 
 class WebGLContextLossHandler;
 class WebGLObserver;
 class WebGLContextBoundObject;
 class WebGLActiveInfo;
 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;
-
+struct WebGLVertexAttribData;
 
 namespace dom {
 class ImageData;
 class Element;
 
 struct WebGLContextAttributes;
 template<typename> struct Nullable;
 }
 
 namespace gfx {
 class SourceSurface;
 }
 
+typedef WebGLRefPtr<WebGLQuery> WebGLQueryRefPtr;
+
 WebGLTexelFormat GetWebGLTexelFormat(TexInternalFormat format);
 
 void AssertUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint shadow);
 
 struct WebGLContextOptions {
     // these are defaults
     WebGLContextOptions();
 
@@ -345,17 +346,17 @@ public:
     void BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB,
                            GLenum srcAlpha, GLenum dstAlpha);
     GLenum CheckFramebufferStatus(GLenum target);
     void Clear(GLbitfield mask);
     void ClearColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a);
     void ClearDepth(GLclampf v);
     void ClearStencil(GLint v);
     void ColorMask(WebGLboolean r, WebGLboolean g, WebGLboolean b, WebGLboolean a);
-    void CompileShader(WebGLShader *shader);
+    void CompileShader(WebGLShader* shader);
     void CompressedTexImage2D(GLenum target, GLint level,
                               GLenum internalformat, GLsizei width,
                               GLsizei height, GLint border,
                               const dom::ArrayBufferView& view);
     void CompressedTexSubImage2D(GLenum target, GLint level,
                                  GLint xoffset, GLint yoffset,
                                  GLsizei width, GLsizei height,
                                  GLenum format,
@@ -818,40 +819,16 @@ public:
     void Viewport(GLint x, GLint y, GLsizei width, GLsizei height);
 // -----------------------------------------------------------------------------
 // WEBGL_lose_context
 public:
     void LoseContext();
     void RestoreContext();
 
 // -----------------------------------------------------------------------------
-// Asynchronous Queries (WebGLContextAsyncQueries.cpp)
-public:
-    already_AddRefed<WebGLQuery> CreateQuery();
-    void DeleteQuery(WebGLQuery *query);
-    void BeginQuery(GLenum target, WebGLQuery *query);
-    void EndQuery(GLenum target);
-    bool IsQuery(WebGLQuery *query);
-    already_AddRefed<WebGLQuery> GetQuery(GLenum target, GLenum pname);
-    JS::Value GetQueryObject(JSContext* cx, WebGLQuery *query, GLenum pname);
-    void GetQueryObject(JSContext* cx, WebGLQuery *query, GLenum pname,
-                        JS::MutableHandle<JS::Value> retval) {
-        retval.set(GetQueryObject(cx, query, pname));
-    }
-
-private:
-    // ANY_SAMPLES_PASSED(_CONSERVATIVE) slot
-    WebGLRefPtr<WebGLQuery> mActiveOcclusionQuery;
-
-    // LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN slot
-    WebGLRefPtr<WebGLQuery> mActiveTransformFeedbackQuery;
-
-    WebGLRefPtr<WebGLQuery>* GetQueryTargetSlot(GLenum target, const char* infos);
-
-// -----------------------------------------------------------------------------
 // Buffer Objects (WebGLContextBuffers.cpp)
 public:
     void BindBuffer(GLenum target, WebGLBuffer* buf);
     void BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer);
     void BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer,
                          WebGLintptr offset, WebGLsizeiptr size);
     void BufferData(GLenum target, WebGLsizeiptr size, GLenum usage);
     void BufferData(GLenum target, const dom::ArrayBufferView &data,
@@ -875,16 +852,24 @@ private:
     WebGLRefPtr<WebGLBuffer> mBoundTransformFeedbackBuffer;
 
     // these two functions emit INVALID_ENUM for invalid `target`.
     WebGLRefPtr<WebGLBuffer>* GetBufferSlotByTarget(GLenum target, const char* infos);
     WebGLRefPtr<WebGLBuffer>* GetBufferSlotByTargetIndexed(GLenum target, GLuint index, const char* infos);
     bool ValidateBufferUsageEnum(GLenum target, const char* infos);
 
 // -----------------------------------------------------------------------------
+// Queries (WebGL2ContextQueries.cpp)
+protected:
+    WebGLQueryRefPtr* GetQueryTargetSlot(GLenum target);
+
+    WebGLQueryRefPtr mActiveOcclusionQuery;
+    WebGLQueryRefPtr mActiveTransformFeedbackQuery;
+
+// -----------------------------------------------------------------------------
 // State and State Requests (WebGLContextState.cpp)
 public:
     void Disable(GLenum cap);
     void Enable(GLenum cap);
     bool GetStencilBits(GLint* out_stencilBits);
     JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv);
     void GetParameter(JSContext* cx, GLenum pname,
                       JS::MutableHandle<JS::Value> retval, ErrorResult& rv) {
deleted file mode 100644
--- a/dom/canvas/WebGLContextAsyncQueries.cpp
+++ /dev/null
@@ -1,351 +0,0 @@
-/* -*- 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 "WebGLContext.h"
-#include "WebGLQuery.h"
-#include "GLContext.h"
-
-using namespace mozilla;
-
-/*
- * We fake ANY_SAMPLES_PASSED and ANY_SAMPLES_PASSED_CONSERVATIVE with
- * SAMPLES_PASSED on desktop.
- *
- * OpenGL ES 3.0 spec 4.1.6
- *  If the target of the query is ANY_SAMPLES_PASSED_CONSERVATIVE, an implementation
- *  may choose to use a less precise version of the test which can additionally set
- *  the samples-boolean state to TRUE in some other implementation-dependent cases.
- */
-
-static const char*
-GetQueryTargetEnumString(GLenum target)
-{
-    switch (target)
-    {
-        case LOCAL_GL_ANY_SAMPLES_PASSED:
-            return "ANY_SAMPLES_PASSED";
-        case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
-            return "ANY_SAMPLES_PASSED_CONSERVATIVE";
-        case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
-            return "TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN";
-        default:
-            break;
-    }
-
-    MOZ_ASSERT(false, "Unknown query `target`.");
-    return "UNKNOWN_QUERY_TARGET";
-}
-
-static inline GLenum
-SimulateOcclusionQueryTarget(const gl::GLContext* gl, GLenum target)
-{
-    MOZ_ASSERT(target == LOCAL_GL_ANY_SAMPLES_PASSED ||
-               target == LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE,
-               "unknown occlusion query target");
-
-    if (gl->IsSupported(gl::GLFeature::occlusion_query_boolean)) {
-        return target;
-    } else if (gl->IsSupported(gl::GLFeature::occlusion_query2)) {
-        return LOCAL_GL_ANY_SAMPLES_PASSED;
-    }
-
-    return LOCAL_GL_SAMPLES_PASSED;
-}
-
-already_AddRefed<WebGLQuery>
-WebGLContext::CreateQuery()
-{
-    if (IsContextLost())
-        return nullptr;
-
-    if (mActiveOcclusionQuery && !gl->IsGLES()) {
-        /* http://www.opengl.org/registry/specs/ARB/occlusion_query.txt
-         * Calling either GenQueriesARB or DeleteQueriesARB while any query of
-         * any target is active causes an INVALID_OPERATION error to be
-         * generated.
-         */
-        GenerateWarning("createQuery: the WebGL 2 prototype might generate INVALID_OPERATION"
-                        "when creating a query object while one other is active.");
-        /*
-         * We *need* to lock webgl2 to GL>=3.0 on desktop, but we don't have a good
-         * mechanism to do this yet. See bug 898404.
-         */
-    }
-
-    nsRefPtr<WebGLQuery> globj = new WebGLQuery(this);
-
-    return globj.forget();
-}
-
-void
-WebGLContext::DeleteQuery(WebGLQuery *query)
-{
-    if (IsContextLost())
-        return;
-
-    if (!query)
-        return;
-
-    if (query->IsDeleted())
-        return;
-
-    if (query->IsActive()) {
-        EndQuery(query->mType);
-    }
-
-    if (mActiveOcclusionQuery && !gl->IsGLES()) {
-        /* http://www.opengl.org/registry/specs/ARB/occlusion_query.txt
-         * Calling either GenQueriesARB or DeleteQueriesARB while any query of
-         * any target is active causes an INVALID_OPERATION error to be
-         * generated.
-         */
-        GenerateWarning("deleteQuery: the WebGL 2 prototype might generate INVALID_OPERATION"
-                        "when deleting a query object while one other is active.");
-    }
-
-    query->RequestDelete();
-}
-
-void
-WebGLContext::BeginQuery(GLenum target, WebGLQuery *query)
-{
-    if (IsContextLost())
-        return;
-
-    WebGLRefPtr<WebGLQuery>* targetSlot = GetQueryTargetSlot(target, "beginQuery");
-    if (!targetSlot) {
-        return;
-    }
-
-    if (!query) {
-        /* SPECS BeginQuery.1
-         * http://www.khronos.org/registry/gles/extensions/EXT/EXT_occlusion_query_boolean.txt
-         * BeginQueryEXT sets the active query object name for the query type given
-         * by <target> to <id>. If BeginQueryEXT is called with an <id> of zero, if
-         * the active query object name for <target> is non-zero (for the targets
-         * ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if the
-         * active query for either target is non-zero), if <id> is the name of an
-         * existing query object whose type does not match <target>, or if <id> is the
-         * active query object name for any query type, the error INVALID_OPERATION is
-         * generated.
-         */
-        ErrorInvalidOperation("beginQuery: query should not be null");
-        return;
-    }
-
-    if (query->IsDeleted()) {
-        /* http://www.khronos.org/registry/gles/extensions/EXT/EXT_occlusion_query_boolean.txt
-         * BeginQueryEXT fails and an INVALID_OPERATION error is generated if <id>
-         * is not a name returned from a previous call to GenQueriesEXT, or if such
-         * a name has since been deleted with DeleteQueriesEXT.
-         */
-        ErrorInvalidOperation("beginQuery: query has been deleted");
-        return;
-    }
-
-    if (query->HasEverBeenActive() &&
-        query->mType != target)
-    {
-        /*
-         * See SPECS BeginQuery.1
-         */
-        ErrorInvalidOperation("beginQuery: target doesn't match with the query type");
-        return;
-    }
-
-    if (*targetSlot) {
-        /*
-         * See SPECS BeginQuery.1
-         */
-        ErrorInvalidOperation("beginQuery: an other query already active");
-        return;
-    }
-
-    if (!query->HasEverBeenActive()) {
-        query->mType = target;
-    }
-
-    MakeContextCurrent();
-
-    if (target == LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) {
-        gl->fBeginQuery(LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query->mGLName);
-    } else {
-        gl->fBeginQuery(SimulateOcclusionQueryTarget(gl, target), query->mGLName);
-    }
-
-    *targetSlot = query;
-}
-
-void
-WebGLContext::EndQuery(GLenum target)
-{
-    if (IsContextLost())
-        return;
-
-    WebGLRefPtr<WebGLQuery>* targetSlot = GetQueryTargetSlot(target, "endQuery");
-    if (!targetSlot) {
-        return;
-    }
-
-    if (!*targetSlot ||
-        target != (*targetSlot)->mType)
-    {
-        /* http://www.khronos.org/registry/gles/extensions/EXT/EXT_occlusion_query_boolean.txt
-         * marks the end of the sequence of commands to be tracked for the query type
-         * given by <target>. The active query object for <target> is updated to
-         * indicate that query results are not available, and the active query object
-         * name for <target> is reset to zero. When the commands issued prior to
-         * EndQueryEXT have completed and a final query result is available, the
-         * query object active when EndQueryEXT is called is updated by the GL. The
-         * query object is updated to indicate that the query results are available
-         * and to contain the query result. If the active query object name for
-         * <target> is zero when EndQueryEXT is called, the error INVALID_OPERATION
-         * is generated.
-         */
-        ErrorInvalidOperation("endQuery: There is no active query of type %s.",
-                              GetQueryTargetEnumString(target));
-        return;
-    }
-
-    MakeContextCurrent();
-
-    if (target == LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) {
-        gl->fEndQuery(LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
-    } else {
-        gl->fEndQuery(SimulateOcclusionQueryTarget(gl, target));
-    }
-
-    *targetSlot = nullptr;
-}
-
-bool
-WebGLContext::IsQuery(WebGLQuery *query)
-{
-    if (IsContextLost())
-        return false;
-
-    if (!query)
-        return false;
-
-    return ValidateObjectAllowDeleted("isQuery", query) &&
-           !query->IsDeleted() &&
-           query->HasEverBeenActive();
-}
-
-already_AddRefed<WebGLQuery>
-WebGLContext::GetQuery(GLenum target, GLenum pname)
-{
-    if (IsContextLost())
-        return nullptr;
-
-    WebGLRefPtr<WebGLQuery>* targetSlot = GetQueryTargetSlot(target, "getQuery");
-    if (!targetSlot) {
-        return nullptr;
-    }
-
-    if (pname != LOCAL_GL_CURRENT_QUERY) {
-        /* OpenGL ES 3.0 spec 6.1.7
-         *  pname must be CURRENT_QUERY.
-         */
-        ErrorInvalidEnum("getQuery: pname must be CURRENT_QUERY");
-        return nullptr;
-    }
-
-    nsRefPtr<WebGLQuery> tmp = targetSlot->get();
-    return tmp.forget();
-}
-
-JS::Value
-WebGLContext::GetQueryObject(JSContext* cx, WebGLQuery *query, GLenum pname)
-{
-    if (IsContextLost())
-        return JS::NullValue();
-
-    if (!query) {
-        /* OpenGL ES 3.0 spec 6.1.7 (spec getQueryObject 1)
-         *  If id is not the name of a query object, or if the query object named by id is
-         *  currently active, then an INVALID_OPERATION error is generated. pname must be
-         *  QUERY_RESULT or QUERY_RESULT_AVAILABLE.
-         */
-        ErrorInvalidOperation("getQueryObject: query should not be null");
-        return JS::NullValue();
-    }
-
-    if (query->IsDeleted()) {
-        // See (spec getQueryObject 1)
-        ErrorInvalidOperation("getQueryObject: query has been deleted");
-        return JS::NullValue();
-    }
-
-    if (query->IsActive()) {
-        // See (spec getQueryObject 1)
-        ErrorInvalidOperation("getQueryObject: query is active");
-        return JS::NullValue();
-    }
-
-    if (!query->HasEverBeenActive()) {
-        /* See (spec getQueryObject 1)
-         *  If this instance of WebGLQuery has never been active before, that mean that
-         *  query->mGLName is not a query object yet.
-         */
-        ErrorInvalidOperation("getQueryObject: query has never been active");
-        return JS::NullValue();
-    }
-
-    switch (pname)
-    {
-        case LOCAL_GL_QUERY_RESULT_AVAILABLE:
-        {
-            GLuint returned = 0;
-
-            MakeContextCurrent();
-            gl->fGetQueryObjectuiv(query->mGLName, LOCAL_GL_QUERY_RESULT_AVAILABLE, &returned);
-
-            return JS::BooleanValue(returned != 0);
-        }
-
-        case LOCAL_GL_QUERY_RESULT:
-        {
-            GLuint returned = 0;
-
-            MakeContextCurrent();
-            gl->fGetQueryObjectuiv(query->mGLName, LOCAL_GL_QUERY_RESULT, &returned);
-
-            if (query->mType == LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) {
-                return JS::NumberValue(uint32_t(returned));
-            }
-
-            /*
-             * test (returned != 0) is important because ARB_occlusion_query on desktop drivers
-             * return the number of samples drawed when the OpenGL ES extension
-             * ARB_occlusion_query_boolean return only a boolean if a sample has been drawed.
-             */
-            return JS::BooleanValue(returned != 0);
-        }
-
-        default:
-            break;
-    }
-
-    ErrorInvalidEnum("getQueryObject: pname must be QUERY_RESULT{_AVAILABLE}");
-    return JS::NullValue();
-}
-
-WebGLRefPtr<WebGLQuery>*
-WebGLContext::GetQueryTargetSlot(GLenum target, const char* infos)
-{
-    switch (target) {
-        case LOCAL_GL_ANY_SAMPLES_PASSED:
-        case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
-            return &mActiveOcclusionQuery;
-        case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
-            return &mActiveTransformFeedbackQuery;
-    }
-
-    ErrorInvalidEnum("%s: unknown query target", infos);
-    return nullptr;
-}
-
-
--- a/dom/canvas/WebGLQuery.cpp
+++ b/dom/canvas/WebGLQuery.cpp
@@ -1,46 +1,51 @@
 /* -*- Mode: C++; tab-width: 20; 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 "WebGLContext.h"
+#include "WebGLQuery.h"
+
 #include "GLContext.h"
-#include "WebGLQuery.h"
+#include "WebGLContext.h"
 #include "mozilla/dom/WebGL2RenderingContextBinding.h"
 #include "nsContentUtils.h"
 
 using namespace mozilla;
 
 JSObject*
-WebGLQuery::WrapObject(JSContext *cx) {
+WebGLQuery::WrapObject(JSContext* cx)
+{
     return dom::WebGLQueryBinding::Wrap(cx, this);
 }
 
 WebGLQuery::WebGLQuery(WebGLContext* context)
     : WebGLContextBoundObject(context)
     , mGLName(0)
     , mType(0)
 {
     mContext->mQueries.insertBack(this);
 
     mContext->MakeContextCurrent();
     mContext->gl->fGenQueries(1, &mGLName);
 }
 
-void WebGLQuery::Delete() {
+void
+WebGLQuery::Delete()
+{
     mContext->MakeContextCurrent();
     mContext->gl->fDeleteQueries(1, &mGLName);
     LinkedListElement<WebGLQuery>::removeFrom(mContext->mQueries);
 }
 
-bool WebGLQuery::IsActive() const
+bool
+WebGLQuery::IsActive() const
 {
-    WebGLRefPtr<WebGLQuery>* targetSlot = mContext->GetQueryTargetSlot(mType, "WebGLQuery::IsActive()");
+    WebGLRefPtr<WebGLQuery>* targetSlot = mContext->GetQueryTargetSlot(mType);
 
     MOZ_ASSERT(targetSlot, "unknown query object's type");
 
     return targetSlot && *targetSlot == this;
 }
 
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLQuery)
--- a/dom/canvas/WebGLQuery.h
+++ b/dom/canvas/WebGLQuery.h
@@ -68,14 +68,14 @@ private:
 
     // -------------------------------------------------------------------------
     // MEMBERS
     GLuint mGLName;
     GLenum mType;
 
     // -------------------------------------------------------------------------
     // FRIENDSHIPS
-    friend class WebGLContext;
+    friend class WebGL2Context;
 };
 
 } // namespace mozilla
 
 #endif
--- a/dom/canvas/moz.build
+++ b/dom/canvas/moz.build
@@ -50,17 +50,16 @@ UNIFIED_SOURCES += [
     'WebGL2ContextSync.cpp',
     'WebGL2ContextTextures.cpp',
     'WebGL2ContextTransformFeedback.cpp',
     'WebGL2ContextUniforms.cpp',
     'WebGL2ContextVAOs.cpp',
     'WebGLActiveInfo.cpp',
     'WebGLBuffer.cpp',
     'WebGLContext.cpp',
-    'WebGLContextAsyncQueries.cpp',
     'WebGLContextBuffers.cpp',
     'WebGLContextDraw.cpp',
     'WebGLContextExtensions.cpp',
     'WebGLContextFramebufferOperations.cpp',
     'WebGLContextGL.cpp',
     'WebGLContextLossHandler.cpp',
     'WebGLContextReporter.cpp',
     'WebGLContextState.cpp',