Bug 1048719 - [WebGL2] Query objects. r=jgilbert
authorDan Glastonbury <dglastonbury@mozilla.com>
Mon, 03 Nov 2014 15:35:04 +1000
changeset 217312 e5bccb2e00cbe1e07934712b7850389dd874265b
parent 217311 f7705f553b85bc361857c72300bc279421cf9aa5
child 217313 13aa9ac1791ea6a8a3b649d7920245589b28d286
push id27877
push usercbook@mozilla.com
push dateTue, 25 Nov 2014 11:48:25 +0000
treeherdermozilla-central@4631a7474d8a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert
bugs1048719
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 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',