Bug 1155470 - Fix queries. r=jgilbert
authorDan Glastonbury <dan.glastonbury@gmail.com>
Fri, 17 Apr 2015 11:17:07 +1000
changeset 270286 f67a0b28268035b608766a7e6a69a0b4659d4dc0
parent 270285 9b75aac198d0480ed6171099d086d37da97f29ff
child 270287 2dfff5537a5da668630d91c5b7ea95b268bff3d8
push id4830
push userjlund@mozilla.com
push dateMon, 29 Jun 2015 20:18:48 +0000
treeherdermozilla-beta@4c2175bb0420 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert
bugs1155470
milestone40.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 1155470 - Fix queries. r=jgilbert es3fTransformFeedbackTests exposed problems with queries. Queries are needed to get the number of transformed primitives.
dom/canvas/WebGL1Context.cpp
dom/canvas/WebGL1Context.h
dom/canvas/WebGL2Context.h
dom/canvas/WebGL2ContextQueries.cpp
dom/canvas/WebGLContext.h
dom/canvas/WebGLQuery.cpp
--- a/dom/canvas/WebGL1Context.cpp
+++ b/dom/canvas/WebGL1Context.cpp
@@ -26,16 +26,23 @@ WebGL1Context::~WebGL1Context()
 }
 
 JSObject*
 WebGL1Context::WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto)
 {
     return dom::WebGLRenderingContextBinding::Wrap(cx, this, aGivenProto);
 }
 
+bool
+WebGL1Context::ValidateQueryTarget(GLenum target, const char* info)
+{
+    // TODO: Implement this for EXT_disjoint_timer
+    return false;
+}
+
 } // namespace mozilla
 
 nsresult
 NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** out_result)
 {
     mozilla::Telemetry::Accumulate(mozilla::Telemetry::CANVAS_WEBGL_USED, 1);
 
     nsIDOMWebGLRenderingContext* ctx = mozilla::WebGL1Context::Create();
--- a/dom/canvas/WebGL1Context.h
+++ b/dom/canvas/WebGL1Context.h
@@ -30,15 +30,15 @@ public:
     virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
     virtual bool ValidateAttribPointerType(bool integerMode, GLenum type, GLsizei* alignment, const char* info) override;
     virtual bool ValidateBufferTarget(GLenum target, const char* info) override;
     virtual bool ValidateBufferIndexedTarget(GLenum target, const char* info) override;
     virtual bool ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer, const char* info) override;
     virtual bool ValidateBufferUsageEnum(GLenum usage, const char* info) override;
-    
+    virtual bool ValidateQueryTarget(GLenum target, const char* info) override;
     virtual bool ValidateUniformMatrixTranspose(bool transpose, const char* info) override;
 };
 
 } // namespace mozilla
 
 #endif // WEBGL_1_CONTEXT_H_
--- a/dom/canvas/WebGL2Context.h
+++ b/dom/canvas/WebGL2Context.h
@@ -350,25 +350,27 @@ public:
     void BindVertexArray(WebGLVertexArrayObject* vertexArray);
 */
 
 private:
     WebGL2Context();
 
     JS::Value GetTexParameterInternal(const TexTarget& target, GLenum pname) override;
 
+    void UpdateBoundQuery(GLenum target, WebGLQuery* query);
+
     bool ValidateSizedInternalFormat(GLenum internalFormat, const char* info);
     bool ValidateTexStorage(GLenum target, GLsizei levels, GLenum internalformat,
                                 GLsizei width, GLsizei height, GLsizei depth,
                                 const char* info);
 
     virtual bool ValidateAttribPointerType(bool integerMode, GLenum type, GLsizei* alignment, const char* info) override;
     virtual bool ValidateBufferTarget(GLenum target, const char* info) override;
     virtual bool ValidateBufferIndexedTarget(GLenum target, const char* info) override;
     virtual bool ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer, const char* info) override;
     virtual bool ValidateBufferUsageEnum(GLenum usage, const char* info) override;
-
+    virtual bool ValidateQueryTarget(GLenum target, const char* info) override;
     virtual bool ValidateUniformMatrixTranspose(bool transpose, const char* info) override;
 };
 
 } // namespace mozilla
 
 #endif
--- a/dom/canvas/WebGL2ContextQueries.cpp
+++ b/dom/canvas/WebGL2ContextQueries.cpp
@@ -2,18 +2,17 @@
 /* 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;
+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
@@ -21,24 +20,24 @@ using namespace mozilla::dom;
  *     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;
+    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)
@@ -51,29 +50,33 @@ SimulateOcclusionQueryTarget(const gl::G
         return target;
     } else if (gl->IsSupported(gl::GLFeature::occlusion_query2)) {
         return LOCAL_GL_ANY_SAMPLES_PASSED;
     }
 
     return LOCAL_GL_SAMPLES_PASSED;
 }
 
-WebGLRefPtr<WebGLQuery>*
-WebGLContext::GetQueryTargetSlot(GLenum target)
+WebGLRefPtr<WebGLQuery>&
+WebGLContext::GetQuerySlotByTarget(GLenum target)
 {
+    /* This function assumes that target has been validated for either
+     * WebGL1 or WebGL2.
+     */
     switch (target) {
-        case LOCAL_GL_ANY_SAMPLES_PASSED:
-        case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
-            return &mActiveOcclusionQuery;
+    case LOCAL_GL_ANY_SAMPLES_PASSED:
+    case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+        return mActiveOcclusionQuery;
 
-        case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
-            return &mActiveTransformFeedbackQuery;
+    case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+        return mActiveTransformFeedbackQuery;
+
+    default:
+        MOZ_CRASH("Should not get here.");
     }
-
-    return nullptr;
 }
 
 
 // -------------------------------------------------------------------------
 // Query Objects
 
 already_AddRefed<WebGLQuery>
 WebGL2Context::CreateQuery()
@@ -147,21 +150,18 @@ WebGL2Context::IsQuery(WebGLQuery* query
 }
 
 void
 WebGL2Context::BeginQuery(GLenum target, WebGLQuery* query)
 {
     if (IsContextLost())
         return;
 
-    WebGLRefPtr<WebGLQuery>* targetSlot = GetQueryTargetSlot(target);
-    if (!targetSlot) {
-        ErrorInvalidEnum("beginQuery: unknown query target");
+    if (!ValidateQueryTarget(target, "beginQuery"))
         return;
-    }
 
     if (!query) {
         /* From GLES's EXT_occlusion_query_boolean:
          *     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
@@ -188,51 +188,50 @@ WebGL2Context::BeginQuery(GLenum target,
     if (query->HasEverBeenActive() &&
         query->mType != target)
     {
         ErrorInvalidOperation("beginQuery: Target doesn't match with the query"
                               " type.");
         return;
     }
 
-    if (*targetSlot) {
-        ErrorInvalidOperation("beginQuery: An other query already active.");
-        return;
-    }
+    WebGLRefPtr<WebGLQuery>& querySlot = GetQuerySlotByTarget(target);
+    WebGLQuery* activeQuery = querySlot.get();
+    if (activeQuery)
+        return ErrorInvalidOperation("beginQuery: An other query already active.");
 
     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;
+    UpdateBoundQuery(target, query);
 }
 
 void
 WebGL2Context::EndQuery(GLenum target)
 {
     if (IsContextLost())
         return;
 
-    WebGLRefPtr<WebGLQuery>* targetSlot = GetQueryTargetSlot(target);
-    if (!targetSlot) {
-        ErrorInvalidEnum("endQuery: unknown query target");
+    if (!ValidateQueryTarget(target, "endQuery"))
         return;
-    }
 
-    if (!*targetSlot ||
-        target != (*targetSlot)->mType)
+    WebGLRefPtr<WebGLQuery>& querySlot = GetQuerySlotByTarget(target);
+    WebGLQuery* activeQuery = querySlot.get();
+
+    if (!activeQuery || target != activeQuery->mType)
     {
         /* From GLES's EXT_occlusion_query_boolean:
          *     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
@@ -250,40 +249,39 @@ WebGL2Context::EndQuery(GLenum target)
     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;
+    UpdateBoundQuery(target, 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");
+    if (!ValidateQueryTarget(target, "getQuery"))
         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();
+    WebGLRefPtr<WebGLQuery>& targetSlot = GetQuerySlotByTarget(target);
+
+    nsRefPtr<WebGLQuery> tmp = targetSlot.get();
     return tmp.forget();
 }
 
 void
 WebGL2Context::GetQueryParameter(JSContext*, WebGLQuery* query, GLenum pname,
                                  JS::MutableHandleValue retval)
 {
     retval.set(JS::NullValue());
@@ -348,8 +346,32 @@ WebGL2Context::GetQueryParameter(JSConte
         return;
 
     default:
         break;
     }
 
     ErrorInvalidEnum("getQueryObject: `pname` must be QUERY_RESULT{_AVAILABLE}.");
 }
+
+void
+WebGL2Context::UpdateBoundQuery(GLenum target, WebGLQuery* query)
+{
+    WebGLRefPtr<WebGLQuery>& querySlot = GetQuerySlotByTarget(target);
+    querySlot = query;
+}
+
+bool
+WebGL2Context::ValidateQueryTarget(GLenum target, const char* info)
+{
+    switch (target) {
+    case LOCAL_GL_ANY_SAMPLES_PASSED:
+    case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+    case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+        return true;
+
+    default:
+        ErrorInvalidEnumInfo(info, target);
+        return false;
+    }
+}
+
+} // namespace mozilla
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -931,17 +931,17 @@ protected:
 
     WebGLRefPtr<WebGLBuffer>& GetBufferSlotByTarget(GLenum target);
     WebGLRefPtr<WebGLBuffer>& GetBufferSlotByTargetIndexed(GLenum target,
                                                            GLuint index);
 
 // -----------------------------------------------------------------------------
 // Queries (WebGL2ContextQueries.cpp)
 protected:
-    WebGLRefPtr<WebGLQuery>* GetQueryTargetSlot(GLenum target);
+    WebGLRefPtr<WebGLQuery>& GetQuerySlotByTarget(GLenum target);
 
     WebGLRefPtr<WebGLQuery> mActiveOcclusionQuery;
     WebGLRefPtr<WebGLQuery> mActiveTransformFeedbackQuery;
 
 // -----------------------------------------------------------------------------
 // State and State Requests (WebGLContextState.cpp)
 public:
     void Disable(GLenum cap);
@@ -1384,16 +1384,17 @@ private:
 private:
     // -------------------------------------------------------------------------
     // Context customization points
     virtual bool ValidateAttribPointerType(bool integerMode, GLenum type, GLsizei* alignment, const char* info) = 0;
     virtual bool ValidateBufferTarget(GLenum target, const char* info) = 0;
     virtual bool ValidateBufferIndexedTarget(GLenum target, const char* info) = 0;
     virtual bool ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer, const char* info) = 0;
     virtual bool ValidateBufferUsageEnum(GLenum usage, const char* info) = 0;
+    virtual bool ValidateQueryTarget(GLenum usage, const char* info) = 0;
     virtual bool ValidateUniformMatrixTranspose(bool transpose, const char* info) = 0;
 
 protected:
     int32_t MaxTextureSizeForTarget(TexTarget target) const {
         return (target == LOCAL_GL_TEXTURE_2D) ? mGLMaxTextureSize
                                                : mGLMaxCubeMapTextureSize;
     }
 
--- a/dom/canvas/WebGLQuery.cpp
+++ b/dom/canvas/WebGLQuery.cpp
@@ -35,20 +35,19 @@ WebGLQuery::Delete()
     mContext->MakeContextCurrent();
     mContext->gl->fDeleteQueries(1, &mGLName);
     LinkedListElement<WebGLQuery>::removeFrom(mContext->mQueries);
 }
 
 bool
 WebGLQuery::IsActive() const
 {
-    WebGLRefPtr<WebGLQuery>* targetSlot = mContext->GetQueryTargetSlot(mType);
+    WebGLRefPtr<WebGLQuery>& targetSlot = mContext->GetQuerySlotByTarget(mType);
 
-    MOZ_ASSERT(targetSlot, "unknown query object's type");
-    return targetSlot && *targetSlot == this;
+    return targetSlot.get() == this;
 }
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLQuery)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLQuery, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLQuery, Release)
 
 } // namespace mozilla